Lists are the most used data structure in Java code; using them idiomatically is a daily skill.
The Collections Framework in java.util provides interfaces (List, Set, Map, Queue, Deque) and implementations. You program to the interface and pick the implementation once, at construction.
A List is an ordered sequence that allows duplicates and index access. ArrayList is the default choice: backed by a resizable array, fast get(i) and fast appends. LinkedList is rarely the right answer — despite theory, it is slower than ArrayList for almost every real workload. For queues and stacks, use ArrayDeque.
Core operations: add(x), add(i, x), get(i), set(i, x), remove(i) or remove(obj), size(), isEmpty(), contains(x), indexOf(x).
Create small fixed lists with List.of("a", "b"). These are unmodifiable: add throws UnsupportedOperationException, and they reject null elements. When you need a mutable copy, write new ArrayList<>(List.of(...)).
Sorting: list.sort(Comparator.naturalOrder()) or with a comparator built from key extractors:
people.sort(Comparator.comparing(Person::lastName).thenComparing(Person::age));To remove elements matching a condition, use list.removeIf(x -> x.isBlank()) rather than removing inside a for-each loop, which throws ConcurrentModificationException.
Watch remove on a List<Integer>: list.remove(1) removes the element at index 1, while list.remove(Integer.valueOf(1)) removes the value 1.
Since Java 21, List is a SequencedCollection, giving getFirst(), getLast(), removeLast() and reversed().
Example
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class ListsDemo {
record Person(String name, int age) { }
public static void main(String[] args) {
List<Person> people = new ArrayList<>(List.of(
new Person("Cy", 41), new Person("Ana", 29), new Person("Bo", 29)));
people.sort(Comparator.comparing(Person::age).thenComparing(Person::name));
System.out.println(people.getFirst().name()); // Ana (Java 21)
people.removeIf(p -> p.age() > 40);
System.out.println(people.size()); // 2
List<Integer> nums = new ArrayList<>(List.of(5, 1, 7));
nums.remove(1); // removes index 1 -> [5, 7]
nums.remove(Integer.valueOf(7)); // removes value 7 -> [5]
System.out.println(nums); // [5]
List<String> fixed = List.of("x", "y"); // fixed.add("z") would throw
System.out.println(fixed.reversed()); // [y, x]
}
}Remember
- Declare
List<T>, constructArrayList— it's the right default List.ofis unmodifiable and null-hostile; copy intoArrayListto mutate- Sort with
Comparator.comparing(...).thenComparing(...); filter out withremoveIf
Watch out for
- Calling
remove(int)on aList<Integer>when you meant to remove a value.