Skip to content

We'll start with Part 1: Java Collections Framework Overview. This is foundational. If you don't understand why the framework exists and how it's organized, the internal implementations of ArrayList, HashMap, and ConcurrentHashMap won't make as much sense.


Part 1 β€” Java Collections Framework OverviewΒΆ

1. What is the Java Collections Framework (JCF)?ΒΆ

The Java Collections Framework (JCF) is a unified architecture for storing, manipulating, and accessing groups of objects.

It provides:

  • Interfaces (contracts)
  • Implementations (classes)
  • Algorithms (utility methods)

Instead of writing your own data structures, you use well-tested implementations provided by the JDK.

Examples:

  • ArrayList
  • LinkedList
  • HashMap
  • HashSet
  • TreeMap
  • PriorityQueue

2. Why was the Collections Framework introduced?ΒΆ

Before JDK 1.2, Java had legacy classes like:

  • Vector
  • Hashtable
  • Stack
  • Dictionary
  • Enumeration

Problems:

  • No common interfaces
  • Inconsistent APIs
  • Limited reusability
  • Mostly synchronized (poor performance in single-threaded code)
  • Difficult to write generic algorithms

Example:

Vector vector = new Vector();
Hashtable table = new Hashtable();

These classes worked differently despite solving similar problems.

SolutionΒΆ

JDK 1.2 introduced the Collections Framework with common interfaces:

Collection
     |
-------------------------
|       |       |
List    Set    Queue

Map (separate hierarchy)

Now algorithms can work with interfaces instead of concrete classes.

Example:

List<String> list = new ArrayList<>();
List<String> list2 = new LinkedList<>();

The code depends on the List interface, so implementations can be swapped with minimal changes.


3. Problems with ArraysΒΆ

Arrays are simple and efficient, but they have limitations.

Problem 1: Fixed SizeΒΆ

int[] arr = new int[5];

The size is fixed at creation.

Need more space?

You must create a new array and copy the elements.

Example:

int[] oldArray = {1,2,3};

int[] newArray = new int[6];

System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);

This copy operation has a time complexity of O(n).


Problem 2: No Built-in OperationsΒΆ

Suppose you want to remove an element:

int[] arr = {10,20,30,40};

Removing 20 requires shifting all later elements:

Before

10 20 30 40

After

10 30 40 _

Time complexity:

O(n)


Problem 3: Arrays Store Fixed-Type ElementsΒΆ

String[] names = new String[10];

Only String objects can be stored.

Generics in collections provide better type safety and flexibility.


Problem 4: No Dynamic GrowthΒΆ

If the array becomes full:

Need larger array

↓

Allocate new memory

↓

Copy old elements

↓

Discard old array

ArrayList automates this process.


Problem 5: Poor APIΒΆ

Arrays provide almost no useful methods.

Collections provide operations like:

add()

remove()

contains()

iterator()

stream()

sort()

4. Collection vs Collections vs StreamΒΆ

This is a very common interview question.

Feature Collection Collections Stream
Type Interface Utility class Interface
Purpose Store elements Utility algorithms Process data
Package java.util java.util java.util.stream
Mutable Yes (generally) N/A No
Stores data Yes No No
Introduced JDK 1.2 JDK 1.2 Java 8

CollectionΒΆ

Represents a group of objects.

Collection<String> c = new ArrayList<>();

CollectionsΒΆ

Utility class with static methods.

Collections.sort(list);

Collections.reverse(list);

Collections.shuffle(list);

StreamΒΆ

Used for processing data declaratively.

list.stream()
    .filter(x -> x.startsWith("A"))
    .sorted()
    .forEach(System.out::println);

Streams do not modify the source collection unless you explicitly perform mutating operations elsewhere.


5. Iterable HierarchyΒΆ

Every collection that can be traversed implements Iterable.

Iterable
    |
Collection
    |
-------------------------
|        |       |
List     Set    Queue

The Iterable interface defines one essential method:

Iterator<T> iterator();

This is why you can use the enhanced for loop.

Example:

List<String> list = List.of("A", "B", "C");

for (String s : list) {
    System.out.println(s);
}

The compiler translates it roughly into:

Iterator<String> it = list.iterator();

while (it.hasNext()) {
    String s = it.next();
    System.out.println(s);
}

6. Complete Collections HierarchyΒΆ

                Iterable
                    |
              Collection
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚         β”‚         β”‚
     List      Set      Queue
      β”‚         β”‚         β”‚
 ArrayList   HashSet  PriorityQueue
 LinkedList  TreeSet  ArrayDeque
 Vector
 Stack

Map (Separate Hierarchy)

Map
 β”œβ”€β”€ HashMap
 β”œβ”€β”€ LinkedHashMap
 β”œβ”€β”€ TreeMap
 β”œβ”€β”€ Hashtable
 β”œβ”€β”€ ConcurrentHashMap
 β”œβ”€β”€ WeakHashMap
 β”œβ”€β”€ IdentityHashMap
 └── EnumMap

Why is Map separate?

A Collection stores individual elements, while a Map stores key-value pairs. Since a map does not conceptually represent a collection of single elements, it is not a subtype of Collection.


7. Core InterfacesΒΆ

Interface Stores Duplicates Ordering
List Elements Yes Preserves insertion order
Set Elements No Depends on implementation
Queue Elements Usually yes FIFO or priority-based
Map Key-value pairs Duplicate keys not allowed Depends on implementation

8. Choosing the Right CollectionΒΆ

Requirement Collection
Fast random access ArrayList
Frequent insertions/removals in the middle LinkedList (though often ArrayList still performs better in practice due to cache locality)
Unique elements HashSet
Sorted unique elements TreeSet
Key-value lookup HashMap
Sorted key-value pairs TreeMap
Thread-safe concurrent map ConcurrentHashMap
Priority processing PriorityQueue
Fast deque operations ArrayDeque

Interview note: Don't choose LinkedList automatically for insertions/deletions. While its insertion is O(1) once you have the node, finding that node is typically O(n). For many real-world workloads, ArrayList is faster because of better CPU cache locality.


9. Time Complexity OverviewΒΆ

Collection Access Search Insert (end) Insert (middle) Delete
ArrayList O(1) O(n) Amortized O(1) O(n) O(n)
LinkedList O(n) O(n) O(1) O(1)* O(1)*
HashSet N/A O(1) average O(1) average N/A O(1) average
HashMap N/A O(1) average O(1) average N/A O(1) average
TreeSet N/A O(log n) O(log n) N/A O(log n)
TreeMap N/A O(log n) O(log n) N/A O(log n)

*Assuming you already have a reference to the target node.


10. Interview QuestionsΒΆ

Q1. Why was the Collections Framework introduced?ΒΆ

Answer: To provide a unified architecture for data structures, common interfaces, reusable algorithms, improved code reuse, and consistent APIs.


Q2. Why doesn't Map extend Collection?ΒΆ

Answer: Because Collection represents a group of individual elements, while Map represents mappings from keys to values.


Q3. Difference between Collection and Collections?ΒΆ

Answer:

  • Collection is an interface.
  • Collections is a utility class containing static helper methods.

Q4. Difference between Collection and Iterable?ΒΆ

Answer:

  • Iterable provides traversal via iterator().
  • Collection extends Iterable and adds methods such as add(), remove(), size(), and contains().

Q5. Which interface supports the enhanced for loop?ΒΆ

Answer: Iterable.


Key TakeawaysΒΆ

  • Understand why JCF was introduced, not just what it contains.
  • Know the distinction between Collection, Collections, Map, and Stream.
  • Remember that Map is a separate hierarchy.
  • Learn the high-level hierarchy before diving into implementations.
  • Be comfortable with the basic time complexities of common collections.

In the next part, we'll do a deep dive into ArrayList, covering its internal implementation, dynamic resizing, growth algorithm, modCount, fail-fast iterators, memory layout, and performance characteristics in detail.