Java Collections β€” List, Set, Map, Queue and the Java Collections Framework

The Java Collections Framework is a unified API for storing and manipulating groups of objects. The four pillars are List (ordered, indexed), Set (no duplicates), Map (key β†’ value) and Queue/Deque (FIFO/LIFO). Each pillar is an interface with multiple implementations that trade off speed, ordering and memory.

Pick the right collection

NeedUseGet / put / contains
Ordered list, frequent indexingArrayListO(1) get / O(1) amortised add
Frequent insert/remove at endsArrayDequeO(1) at both ends
Unique elements, no orderHashSetO(1) average
Unique elements, sortedTreeSetO(log n)
Unique elements, insertion order preservedLinkedHashSetO(1) average
Key β†’ value lookupHashMapO(1) average
Key β†’ value, sorted by keyTreeMapO(log n)
FIFO queue (single-threaded)ArrayDequeO(1)
FIFO queue (multi-threaded)ConcurrentLinkedQueue / LinkedBlockingQueueO(1)

Modern factory methods (Java 9+)

List<String> names    = List.of("Alice", "Bob");           // immutable
Set<Integer> primes   = Set.of(2, 3, 5, 7);                // immutable
Map<String,Integer> m = Map.of("a", 1, "b", 2);            // immutable, max 10 entries
Map<String,Integer> big = Map.ofEntries(
    Map.entry("a", 1),
    Map.entry("b", 2),
    Map.entry("c", 3));                                     // for > 10 entries

Factory collections are immutable β€” calling add throws UnsupportedOperationException. They're also more compact than new ArrayList<>() and friends.

List operations

var list = new ArrayList<String>();
list.add("first");
list.add(0, "zeroth");                    // insert at index 0
list.set(1, "FIRST");                     // replace
list.remove("FIRST");                     // by value
list.remove(0);                           // by index
list.contains("zeroth");                  // O(n) scan

Map operations

var votes = new HashMap<String, Integer>();
votes.put("Alice", 1);
votes.merge("Alice", 1, Integer::sum);    // increment-or-create β€” Java 8+
votes.computeIfAbsent("Bob", k -> 0);     // lazy init

for (var e : votes.entrySet()) {
    System.out.println(e.getKey() + " = " + e.getValue());
}

Iterating safely

// ❌ ConcurrentModificationException
for (String s : list) if (s.isEmpty()) list.remove(s);

// βœ… Use Iterator.remove()
var it = list.iterator();
while (it.hasNext()) if (it.next().isEmpty()) it.remove();

// βœ… Or removeIf β€” Java 8+
list.removeIf(String::isEmpty);

Streams over collections

List<String> longNames = users.stream()
    .filter(u -> u.age() >= 18)
    .map(User::name)
    .filter(n -> n.length() > 5)
    .toList();                            // Java 16+ β€” immutable

Map<String,Long> byCity = users.stream()
    .collect(Collectors.groupingBy(User::city, Collectors.counting()));

All sub-topics

Common mistakes

  • Using LinkedList by default β€” ArrayList is faster for almost every workload, including head/tail operations on small lists.
  • Iterating + removing β€” throws ConcurrentModificationException. Use Iterator.remove() or removeIf.
  • Mutable keys in HashMap β€” if a key's hashCode changes after insertion, you can't find it again.
  • Returning a mutable internal list β€” callers can corrupt your state. Return List.copyOf(internal) or wrap in Collections.unmodifiableList.

Try it & related tools

The JSON to POJO tool generates classes that work with collections (lists of objects, maps as keys). Run snippets in the Java Online Compiler.