Collections

4 posts in this section

Collection Factory Methods (JEP 269): Immutable List, Set, and Map

Why Collection Factory Methods? Before Java 9, creating a small immutable collection was tedious: // Java 8 — three lines, two classes, mutable intermediate List<String> names = Collections.unmodifiableList( Arrays.asList("Alice", "Bob", "Charlie") ); // Java 8 — even worse for Map Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 90); scores.put("Bob", 85); Map<String, Integer> immutableScores = Collections.unmodifiableMap(scores); JEP 269 (Java 9) introduced static factory methods that create truly immutable collections with a single expression:

Continue reading »

Collections and Map Enhancements: forEach, merge, compute, replaceAll

Overview Java 8 didn’t just add Streams — it also enhanced the existing Iterable, Collection, List, and Map interfaces with default methods that cover the most common imperative patterns. Understanding these methods lets you write cleaner code even without streams. The three methods worth memorising immediately are computeIfAbsent (the most useful new Map method), merge (for accumulation patterns), and removeIf (eliminating the iterator-based removal pattern). Together they eliminate the most common sources of verbose boilerplate in collection-heavy code.

Continue reading »

Sequenced Collections (JEP 431): A Unified API for Ordered Collections

The 30-Year Gap in the Collections API Java’s Collections Framework has a fundamental inconsistency: there is no uniform way to access the first or last element of an ordered collection. Before Java 21: // List — index-based var list = List.of("a", "b", "c"); String first = list.get(0); // first element String last = list.get(list.size() - 1); // last element — verbose, error-prone // Deque — special methods Deque<String> deque = new ArrayDeque<>(List.

Continue reading »

Streams API: Lazy Pipelines and the Functional Data Model

The Problem Streams Solve Java loops are not wrong — they are often the right tool. But when a computation is a multi-step pipeline of filter → transform → aggregate, a loop hides the structure of the computation in a tangle of temporary variables and mutated collections. The Streams API makes the structure explicit, lets the JVM optimise it, and composes naturally with lambdas and method references. Consider filtering a list of orders to find the names of active premium customers who spent over $500, sorted alphabetically:

Continue reading »