iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

List / ArrayList

java.util.List is the interface every list-like collection implements: ArrayList (random access, dense), LinkedList (rare in modern Java; reach for ArrayDeque instead), and the immutable List.of(...). Most day-to-day work is on ArrayList plus the Stream API — pick the right one and the rest of your code stays clean.

List operations, immutability, and streams

EXAMPLE
import java.util.*;
import java.util.stream.*;

public class ListsDemo {

    public static void main(String[] args) {
        // 1) Mutable ArrayList — the default
        List<Integer> nums = new ArrayList<>(List.of(3, 1, 4, 1, 5, 9, 2, 6));
        nums.add(5);
        nums.remove(Integer.valueOf(1));    // remove by value (note the boxing)
        nums.set(0, 99);                    // replace at index
        System.out.println(nums);

        // 2) Immutable List.of — throws on any mutation
        List<String> tags = List.of("alpha", "beta", "gamma");
        try { tags.add("delta"); }
        catch (UnsupportedOperationException e) {
            System.out.println("List.of is immutable: " + e.getMessage());
        }

        // 3) Defensive copies — return immutable views from APIs
        List<String> safe = List.copyOf(new ArrayList<>(tags));
        // returns an immutable copy, even if the input is mutable

        // 4) Sorting — natural and custom
        List<String> people = new ArrayList<>(List.of("alice", "charlie", "bob"));
        Collections.sort(people);                      // natural order
        people.sort(Comparator.comparingInt(String::length).reversed());

        // 5) Search — binarySearch on a SORTED list, O(log n)
        Collections.sort(people);
        int idx = Collections.binarySearch(people, "bob");
        System.out.println("bob at index " + idx);

        // 6) Streams — filter/map/reduce without writing a loop
        int evenSquares = nums.stream()
            .filter(n -> n % 2 == 0)
            .mapToInt(n -> n * n)
            .sum();
        System.out.println("sum of even squares: " + evenSquares);

        // 7) Collect to a NEW immutable list (Java 16+)
        List<String> upper = people.stream()
            .map(String::toUpperCase)
            .toList();
        System.out.println(upper);

        // 8) Group-by — Map<K, List<V>> in one line
        List<String> words = List.of("ant", "ape", "bear", "bat", "cat");
        Map<Character, List<String>> byFirst = words.stream()
            .collect(Collectors.groupingBy(w -> w.charAt(0)));
        System.out.println(byFirst);

        // 9) Partitioning into two buckets
        Map<Boolean, List<Integer>> parts = nums.stream()
            .collect(Collectors.partitioningBy(n -> n > 4));
        System.out.println(parts);

        // 10) Iterate without indices (cleanest), or with indices when you need them
        for (var word : words) System.out.print(word + " ");
        System.out.println();
        for (int i = 0; i < words.size(); i++) {
            System.out.println(i + " -> " + words.get(i));
        }
    }
}

Why it matters

Use ArrayList for everything until benchmarks tell you otherwise. LinkedList wins only when you insert/remove at both ends millions of times AND never index — and ArrayDeque is faster for that case anyway. The mental model "LinkedList is good for inserts" predates modern CPU caches and is wrong on real hardware.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
List<Integer> xs = new ArrayList<>();
xs.add(1); xs.add(2); xs.add(3);
System.out.println(xs.get(0));
System.out.println(xs.size());
Try it Yourself »

Discussion

Loading…