Collections are at the heart of Java programming, enabling developers to store, manage, and manipulate groups of objects efficiently. The Java Collections Framework (JCF) provides a standard architecture to represent and work with collections like lists, sets, maps, queues, and more.
With every LTS release, Java introduces updates that improve performance, readability, and usability of these core data structures. Java 21 continues this evolution by fine-tuning concurrent behavior, streamlining stream operations, and enhancing immutability support.
This guide explores the modern capabilities of the Java Collections API as of Java 21, helping you write cleaner, safer, and faster code.
📚 Core Concepts of Java Collections Framework
What is the Java Collections Framework?
The Java Collections Framework is a set of classes and interfaces that implement commonly reusable collection data structures such as:
- List (e.g.,
ArrayList
,LinkedList
) - Set (e.g.,
HashSet
,TreeSet
) - Map (e.g.,
HashMap
,TreeMap
) - Queue (e.g.,
LinkedList
,PriorityQueue
)
Why Collections Matter
Collections make data organization predictable, performance-optimized, and thread-safe (when needed). They allow you to:
- Avoid reinventing data structures
- Improve algorithm efficiency
- Take advantage of multi-core concurrency
- Simplify functional operations using streams and lambdas
🧱 Java Syntax and Structures
Key Interfaces:
List<String> list = new ArrayList<>();
Set<Integer> set = new HashSet<>();
Map<String, Integer> map = new HashMap<>();
Generic Support
List<Double> prices = new LinkedList<>();
🧠 Internal Working and Memory Models
ArrayList
- Backed by a dynamic array
- Resizes (grows) by ~50% when capacity exceeded
O(1)
random access,O(n)
remove
HashMap
- Bucketed hash table
- Uses hashCode and equals()
- Collisions handled via chaining (linked list or tree for high collision count)
⚡ Performance & Big-O Overview
Collection | Access | Insert | Delete | Notes |
---|---|---|---|---|
ArrayList | O(1) | O(1)* | O(n) | *Amortized insert |
LinkedList | O(n) | O(1) | O(1) | Slower access |
HashSet | - | O(1) | O(1) | Based on HashMap |
TreeSet | O(log n) | O(log n) | O(log n) | Sorted |
HashMap | O(1) | O(1) | O(1) | Collisions affect perf |
TreeMap | O(log n) | O(log n) | O(log n) | Red-Black Tree |
📅 Real-World Use Cases
- ArrayList: Logging events, UI elements list, sequential data
- HashSet: Caching unique IDs, removing duplicates
- HashMap: Configuration maps, user profiles
- TreeMap: Leaderboards, schedules sorted by timestamps
- ConcurrentHashMap: Real-time dashboards, shared caches
🛳 Functional Programming in Collections
Java 8+ allows cleaner collection processing using:
List<String> names = List.of("Ava", "Liam", "Noah");
names.stream()
.filter(n -> n.startsWith("A"))
.map(String::toUpperCase)
.forEach(System.out::println);
- Use Predicate, Function, Consumer for composable behavior
🔍 Comparing Similar Collections
HashMap vs TreeMap
Feature | HashMap | TreeMap |
---|---|---|
Ordering | Unordered | Sorted by key |
Performance | Faster | Slower |
Null keys | 1 allowed | Not allowed |
List vs Set
Feature | List | Set |
---|---|---|
Duplicates | Allowed | Not allowed |
Order | Preserved | Depends on impl |
🔁 Refactoring Legacy Code
Legacy:
List list = new ArrayList();
list.add("one");
Modern:
List<String> list = List.of("one", "two");
- Use
List.of()
for immutability - Use diamond operator
<>
- Avoid raw types
📄 Anti-patterns and Fixes
Bad Practice | Recommended Fix |
---|---|
Using raw types (List list ) |
Use generics (List<String> ) |
Using synchronized wrapper | Use concurrent collections |
Modifying immutable collections | Use ArrayList.copyOf() |
📌 What's New in Java Versions?
📅 Java 8
- Streams API
- Lambdas and functional interfaces
Collectors
andOptional
📅 Java 9
List.of()
,Set.of()
,Map.of()
for immutability- Stream enhancements:
takeWhile
,dropWhile
📅 Java 10–17
- Type inference with
var
- Improved stream collectors
📅 Java 21
- Sequenced Collections API (JEP 431): Introduces new
SequencedCollection
,SequencedSet
, andSequencedMap
interfaces- Adds ordering semantics to collections
- Supports
reversed()
view
- Performance improvements to
HashMap
andArrayList
- Better handling of nulls and concurrent access
📊 Conclusion and Key Takeaways
- The Java Collections Framework is a powerful toolset for building data-rich applications.
- Java 21 builds on decades of enhancements, making collections more expressive, performant, and safer.
- Prefer immutability, understand internal structures, and choose the right collection type based on your use case.
🤠 FAQ: Expert-Level Questions
1. What's the difference between List.of()
and Collections.unmodifiableList()
?
List.of()
creates truly immutable collections.unmodifiableList()
can still reflect changes in the original list.
2. How many collisions degrade HashMap
performance?
- More than 8 entries in a bucket switch it from linked list to balanced tree (Java 8+).
3. Can HashSet
contain null?
- Yes, but only one null is allowed.
4. Is TreeMap
thread-safe?
- No. Use
Collections.synchronizedMap()
orConcurrentSkipListMap
for concurrency.
5. When to use LinkedList
over ArrayList
?
- Use
LinkedList
when frequent insertions/removals at the head/tail are needed.
6. How does Java 21's SequencedMap
help?
- It ensures consistent ordering, including reverse order views and better predictability.
7. Are streams thread-safe?
- No. You must manage concurrency separately when parallelizing.
8. What's the default capacity of ArrayList
?
- Initially 10, then grows dynamically.
9. Is it bad to return List<String>
vs ArrayList<String>
?
- Prefer returning interface types (e.g.,
List
) to preserve flexibility.
10. How to detect concurrent modification?
- Java throws
ConcurrentModificationException
during iteration if structure is modified.