java.util Part 1: The Collections Framework

A simple, book-style explanation of Java's Collections Framework

What is the Collections Framework?
The Java Collections Framework is a standardized set of interfaces, classes, algorithms, and supporting mechanisms used to manage groups of objects. Instead of implementing common data structures yourself, Java provides reusable implementations such as ArrayList, LinkedList, HashSet, TreeSet, HashMap, and TreeMap.

1. Why Do We Need the Collections Framework?

A program frequently needs to store a group of objects: students, products, accounts, names, orders, or numbers. Java could provide a different class for every possible requirement, but that would make programs harder to learn and maintain. The Collections Framework provides a common design so that different collection types can be handled in a consistent way.

The framework was designed around several important goals:

  • High performance: common data structures such as dynamic arrays, linked lists, trees, and hash tables are provided.
  • Interoperability: different collection types can be used in a similar manner.
  • Extensibility: developers can create their own collection implementations when necessary.
  • Standard algorithms: operations such as sorting and searching are provided centrally by the Collections class.
  • Common traversal: Iterator provides a standard way to process elements one at a time.
  • Array integration: Java provides mechanisms for moving between arrays and collections.
Important perspective: The framework is based on interfaces. A concrete class such as ArrayList or HashSet provides an implementation of the behavior defined by an interface.

2. The Big Picture

Iterable
Collection<E>
Set<E>
HashSet<E>
TreeSet<E>
List<E>
ArrayList<E>
LinkedList<E>
Queue<E>
PriorityQueue<E>
Map<K,V>
HashMap<K,V>
TreeMap<K,V>

The main collection hierarchy starts with Iterable, then Collection, which is extended by interfaces such as List, Set, and Queue. Map is part of the Collections Framework but is a separate hierarchy because it stores key-value pairs rather than individual collection elements.

3. Collection Interfaces

InterfaceSimple description
Collection<E>Works with groups of objects and forms the foundation of the collection hierarchy.
List<E>Represents a sequence of elements. It provides index-based access and normally allows duplicates.
Set<E>Represents a group of unique elements. Duplicate elements are not allowed.
Queue<E>Represents a collection designed for elements that are waiting to be processed.
Deque<E>Extends Queue and supports operations at both ends of the queue.
SortedSet<E>Extends Set and maintains elements in sorted order.
NavigableSet<E>Extends SortedSet and adds navigation and closest-match search operations.

The framework also uses related interfaces:

  • Iterator — traverses collection elements one at a time.
  • ListIterator — provides richer traversal for lists.
  • Spliterator — supports traversal that can be split, making it useful for parallel processing.
  • Comparator — defines how two objects should be compared.
  • RandomAccess — indicates that a List supports efficient random/index-based access.

4. The Collection Interface

The Collection<E> interface is the foundation of the main collection hierarchy. The type parameter E represents the type of element stored in the collection. Because Collection extends Iterable, its implementations can be processed with the enhanced for loop.

Common Collection methods

MethodPurpose
add(E)Adds an element.
addAll(Collection)Adds all elements from another collection.
remove(Object)Removes an element.
removeAll(Collection)Removes elements that occur in another collection.
retainAll(Collection)Keeps only elements that occur in another collection.
removeIf(Predicate)Removes elements that satisfy a condition.
clear()Removes all elements.
contains(Object)Checks whether an element exists.
containsAll(Collection)Checks whether all elements of another collection are present.
isEmpty()Checks whether the collection contains no elements.
size()Returns the number of elements.
iterator()Returns an Iterator.
toArray()Converts collection contents into an array.
stream()Returns a sequential Stream from the collection.
parallelStream()Returns a stream that can support parallel processing when possible.

5. Modifiable and Unmodifiable Collections

Some collection operations are optional because not every collection supports modification. A collection that permits modification is called modifiable. A collection that does not allow its contents to change is called unmodifiable.

If a modification operation is attempted on an unmodifiable collection, Java can throw UnsupportedOperationException.

6. List Interface

A List represents an ordered sequence of elements. Elements can normally be accessed by an integer index, beginning at zero, and duplicate elements are allowed.

List<String> names = new ArrayList<>(); names.add("Ravi"); names.add("Amit"); names.add("Ravi"); System.out.println(names.get(1));

Output:

Amit

Important List methods

MethodPurpose
add(int, E)Inserts an element at a specific index.
addAll(int, Collection)Inserts another collection at a specific index.
get(int)Returns the element at an index.
set(int, E)Replaces the element at an index.
indexOf(Object)Returns the first matching index, or -1.
lastIndexOf(Object)Returns the last matching index, or -1.
subList(int, int)Provides a view of a portion of the list.
sort(Comparator)Sorts the list according to the supplied comparison rule.
listIterator()Returns a ListIterator.

7. Set Interface

A Set represents a collection in which duplicate elements are not allowed.

Set<String> languages = new HashSet<>(); languages.add("Java"); languages.add("Python"); languages.add("Java"); System.out.println(languages);

Only one occurrence of `"Java"` can be stored.

Think of Set as: "I need unique values."

8. SortedSet and NavigableSet

SortedSet extends Set and adds the idea of sorted elements. NavigableSet extends SortedSet and provides operations for navigating around values, including closest-match searches.

The common concrete implementation is TreeSet.

9. Queue Interface

A Queue represents a collection designed for holding elements before they are processed. Queue operations commonly distinguish between examining, retrieving, and removing the head element.

Queue<String> queue = new LinkedList<>(); queue.offer("A"); queue.offer("B"); queue.offer("C"); System.out.println(queue.poll());

Output:

A

Queue operation families

PurposeCommon methods
Insertadd(), offer()
Examine headelement(), peek()
Remove headremove(), poll()

10. Deque Interface

Deque means double-ended queue. It extends Queue and supports adding, examining, and removing elements from either end.

Deque<String> deque = new ArrayDeque<>(); deque.addFirst("B"); deque.addFirst("A"); deque.addLast("C"); System.out.println(deque);

Conceptually:

Front Back ↓ ↓ [A] ←----------------------→ [B] [C]

11. Common Collection Classes

ClassMain idea
ArrayListResizable-array implementation of List. Efficient for indexed access.
LinkedListLinked-node implementation of List and Deque. Supports list and double-ended queue operations.
HashSetSet implementation based on hashing. Does not guarantee element order.
LinkedHashSetHashSet variant that maintains insertion-order iteration.
TreeSetSorted Set implementation based on a tree.
PriorityQueueQueue implementation that retrieves its head according to its ordering rules.
ArrayDequeResizable-array implementation of Deque.
EnumSetSpecialized Set designed for enum elements.

12. ArrayList

ArrayList<E> is a resizable-array implementation of List. It is particularly useful when your program frequently accesses elements by index.

ArrayList<String> names = new ArrayList<>(); names.add("Ravi"); names.add("Amit"); names.add("Neha"); System.out.println(names.get(0));

Output:

Ravi
Simple rule: If you need a general-purpose List with efficient indexed access, ArrayList is often a natural choice.

13. LinkedList

LinkedList<E> implements List, Deque, and Queue. It provides linked-list behavior and therefore supports operations at both ends.

LinkedList<String> list = new LinkedList<>(); list.add("B"); list.addFirst("A"); list.addLast("C"); System.out.println(list);

Useful methods include:

  • addFirst() / offerFirst()
  • addLast() / offerLast()
  • getFirst() / peekFirst()
  • getLast() / peekLast()
  • removeFirst() / pollFirst()
  • removeLast() / pollLast()

14. HashSet

HashSet<E> uses hashing to store a Set of unique elements. It does not guarantee the order of its elements.

HashSet<String> set = new HashSet<>(); set.add("Beta"); set.add("Alpha"); set.add("Beta"); System.out.println(set);

The duplicate `"Beta"` is not added.

Do not depend on HashSet iteration order. If sorted storage is required, use a suitable sorted collection such as TreeSet.

15. TreeSet

TreeSet is a Set implementation that maintains elements according to sorted ordering.

TreeSet<Integer> numbers = new TreeSet<>(); numbers.add(30); numbers.add(10); numbers.add(20); System.out.println(numbers);

Output:

[10, 20, 30]

16. PriorityQueue

PriorityQueue is a Queue implementation. The element retrieved from its head is determined by the queue's ordering rules.

PriorityQueue<Integer> queue = new PriorityQueue<>(); queue.add(30); queue.add(10); queue.add(20); System.out.println(queue.poll());

With natural ordering for integers, the output is:

10

17. ArrayDeque

ArrayDeque provides a resizable-array implementation of Deque. It can be used as a queue or as a stack.

ArrayDeque<String> stack = new ArrayDeque<>(); stack.push("A"); stack.push("B"); stack.push("C"); System.out.println(stack.pop());

Output:

C

This demonstrates stack behavior: the last element pushed is the first one removed.

18. EnumSet

EnumSet is a specialized Set for enum values. It is designed specifically for use with enum types.

enum Day { MONDAY, TUESDAY, WEDNESDAY } EnumSet<Day> days = EnumSet.of(Day.MONDAY, Day.WEDNESDAY);

19. Iterators

An Iterator provides a standardized way to access elements in a collection one at a time. This means code that traverses one collection can often be adapted easily to another collection.

List<String> names = new ArrayList<>(); names.add("Ravi"); names.add("Amit"); names.add("Neha"); Iterator<String> it = names.iterator(); while (it.hasNext()) { System.out.println(it.next()); }

Common Iterator methods

MethodPurpose
hasNext()Returns true when another element is available.
next()Returns the next element.
remove()Removes the current element when supported by the iterator.
forEachRemaining()Processes remaining elements using the supplied action.

20. ListIterator

ListIterator is designed specifically for Lists. Unlike a basic Iterator, it supports traversal in both directions and provides additional list operations.

List<String> names = new ArrayList<>(); ListIterator<String> it = names.listIterator();

It provides operations such as:

  • hasNext() and next()
  • hasPrevious() and previous()
  • add()
  • set()
  • remove()

21. Spliterator

Java 8 introduced Spliterator. It is an iterator-like mechanism designed to support traversal that can be split into parts, which is useful for parallel processing.

List<String> names = List.of("A", "B", "C", "D"); Spliterator<String> sp = names.spliterator(); sp.forEachRemaining( System.out::println );

22. RandomAccess

RandomAccess is a marker interface. It does not declare methods. When a List implements it, the List indicates that indexed access can be performed efficiently.

ArrayList is an example of a List designed for efficient random access.

23. Map Interfaces

A Map<K,V> stores key-value pairs. The key identifies the value, and keys are unique within a map.

Map<Integer, String> students = new HashMap<>(); students.put(101, "Ravi"); students.put(102, "Amit"); students.put(103, "Neha"); System.out.println(students.get(102));

Output:

Amit
Simple rule: Use a Map when your data has a relationship such as ID → Object, Key → Value, or Name → Score.

Map hierarchy

Map<K,V>
SortedMap<K,V>
TreeMap<K,V>
NavigableMap<K,V>

The framework also defines SortedMap, NavigableMap, and Map.Entry.

24. Important Map Methods

MethodPurpose
put(K,V)Adds or replaces a key-value mapping.
get(Object)Returns the value associated with a key.
remove(Object)Removes a mapping by key.
containsKey(Object)Checks whether a key exists.
containsValue(Object)Checks whether a value exists.
size()Returns the number of mappings.
isEmpty()Checks whether the map contains no mappings.
clear()Removes all mappings.
keySet()Returns a Set view of the keys.
values()Returns a collection view of the values.
entrySet()Returns a Set view of the key-value entries.
putIfAbsent()Adds a mapping only when the key is not already mapped.
getOrDefault()Returns a value or a specified default when the key is absent.

25. Map.Entry

Each key-value pair in a Map can be represented by a Map.Entry<K,V>. This is useful when processing both the key and its value together.

Map<Integer, String> students = new HashMap<>(); students.put(101, "Ravi"); students.put(102, "Amit"); for (Map.Entry<Integer, String> entry : students.entrySet()) { System.out.println( entry.getKey() + " = " + entry.getValue() ); }

26. HashMap

HashMap<K,V> uses a hash table to store mappings. It is designed for efficient get() and put() operations. It does not guarantee the order of its elements.

HashMap<Integer, String> map = new HashMap<>(); map.put(101, "Ravi"); map.put(102, "Amit"); System.out.println(map.get(101));

Output:

Ravi
Remember: HashMap does not promise insertion order or sorted order. If ordering is important, choose a map implementation that provides the required ordering.

27. TreeMap

TreeMap<K,V> uses a tree and maintains its keys according to sorted ordering.

TreeMap<Integer, String> map = new TreeMap<>(); map.put(103, "Neha"); map.put(101, "Ravi"); map.put(102, "Amit"); System.out.println(map);

The keys are maintained in sorted order:

{101=Ravi, 102=Amit, 103=Neha}

28. Other Map Classes

ClassSimple description
HashMapMap implementation based on hashing.
TreeMapMap implementation based on a tree and sorted keys.
LinkedHashMapHashMap variant that supports insertion-order iteration.
EnumMapMap designed for enum keys.
WeakHashMapMap using weak keys, allowing entries to become eligible for garbage collection when their keys are otherwise unused.
IdentityHashMapMap that uses reference identity when comparing keys.

29. Comparators

A Comparator defines how two objects should be compared. This is especially useful when a collection needs an ordering different from an object's natural ordering.

Comparator<String> reverse = (a, b) -> b.compareTo(a); TreeSet<String> set = new TreeSet<>(reverse); set.add("A"); set.add("C"); set.add("B"); System.out.println(set);

The comparator causes the TreeSet to use the comparison rule supplied to it.

30. Collection Algorithms

The Collections class provides static algorithms that operate on collections. This gives the framework a standard way to manipulate collections instead of requiring every collection class to implement its own sorting and searching algorithms.

Common algorithms

MethodPurpose
sort()Sorts a List.
binarySearch()Searches a sorted List.
reverse()Reverses the order of a List.
shuffle()Randomly rearranges a List.
min()Finds the minimum element according to ordering.
max()Finds the maximum element according to ordering.
rotate()Rotates elements in a List.
frequency()Counts occurrences of an object.
fill()Replaces all elements in a List with a specified value.
copy()Copies elements from one List to another.
replaceAll()Replaces all occurrences of one value with another.

Example — Sorting a List

List<Integer> numbers = new ArrayList<>(); numbers.add(30); numbers.add(10); numbers.add(20); Collections.sort(numbers); System.out.println(numbers);

Output:

[10, 20, 30]

31. Unmodifiable Collection Views

The Collections class also provides methods for creating unmodifiable views of collections. These views allow a collection to be exposed without allowing callers to modify it through that view.

List<String> names = new ArrayList<>(); names.add("Java"); List<String> readOnly = Collections.unmodifiableList(names);
An attempt to modify an unmodifiable view through the view can result in UnsupportedOperationException.

32. Arrays and the Collections Framework

Java provides the Arrays utility class for common array operations. The framework also provides ways to move between arrays and collections.

Common Arrays operations

MethodPurpose
sort()Sorts an array.
binarySearch()Searches a sorted array.
fill()Fills an array or part of an array with a value.
copyOf()Creates a copy of an array.
copyOfRange()Copies a specified range of an array.
equals()Compares array contents.
toString()Creates a readable representation of an array.
deepToString()Creates a readable representation for nested arrays.
mismatch()Finds the first index at which two arrays differ.
int[] numbers = {30, 10, 20}; Arrays.sort(numbers); System.out.println( Arrays.toString(numbers) );

Output:

[10, 20, 30]

33. Generics in Collections

Collections use generics to specify the type of elements they store.

ArrayList<String> names = new ArrayList<>(); ArrayList<Integer> numbers = new ArrayList<>(); HashSet<String> languages = new HashSet<>(); HashMap<Integer, String> students = new HashMap<>();

In Map<K,V>, K represents the key type and V represents the value type.

Generic type = type safety.
When you declare List<String>, the compiler knows that the List is intended to contain Strings.

34. Autoboxing and Collections

Collections store object references rather than primitive values. Java's autoboxing feature makes it convenient to work with primitive values.

ArrayList<Integer> numbers = new ArrayList<>(); numbers.add(10); numbers.add(20); numbers.add(30);

The primitive int values are automatically boxed into Integer objects when they are added.

35. A Practical Way to Choose a Collection

Need a sequence?

Use List. A common implementation is ArrayList.

Need unique values?

Use Set. Choose HashSet when sorted order is not required and TreeSet when sorted order is needed.

Need queue behavior?

Use Queue or Deque. Examples include PriorityQueue and ArrayDeque.

Need key-value relationships?

Use Map. Choose HashMap or TreeMap according to ordering requirements.

36. Collection vs Map

CollectionMap
Stores individual elements.Stores key-value pairs.
Examples: List, Set, Queue.Examples: HashMap, TreeMap.
Elements are accessed as collection elements.Values are normally accessed using keys.
Can be traversed through Collection/Iterator mechanisms.Provides views such as keySet(), values(), and entrySet().
Important: A Map is part of the Collections Framework, but it is not a Collection in the strict meaning of the Collection interface.

37. Legacy Classes and Interfaces

Before the Collections Framework was added, Java provided older classes for storing groups of objects. Some of these classes were later integrated with the collection interfaces.

Legacy typeModern perspective
VectorOlder dynamic-array class. Modern List implementations are usually preferred for new code when Vector-specific behavior is not needed.
StackOlder stack class. Deque implementations such as ArrayDeque are generally preferred for stack behavior in new code.
HashtableOlder synchronized map class. Modern Map implementations are generally preferred when its legacy behavior is not required.
DictionaryLegacy abstract class for key-value mappings.
PropertiesLegacy utility class for property data.
EnumerationOlder traversal interface that has been superseded by Iterator for general collection traversal.

38. Complete Example

import java.util.*; public class CollectionDemo { public static void main(String[] args) { // List List<String> names = new ArrayList<>(); names.add("Ravi"); names.add("Amit"); names.add("Neha"); // Set Set<String> uniqueNames = new HashSet<>(); uniqueNames.add("Ravi"); uniqueNames.add("Ravi"); uniqueNames.add("Amit"); // Queue Queue<String> queue = new LinkedList<>(); queue.offer("First"); queue.offer("Second"); // Map Map<Integer, String> students = new HashMap<>(); students.put(101, "Ravi"); students.put(102, "Amit"); System.out.println(names); System.out.println(uniqueNames); System.out.println(queue.poll()); System.out.println(students.get(101)); } }

39. Perspective — How to Think About the Framework

Do not try to memorize every collection class first. Start with the data requirement.

What kind of data do I have? | +-----+-----+ | | | Sequence Unique Key-Value | | | List Set Map | | | ArrayList HashSet HashMap | | | LinkedList TreeSet TreeMap Need queue behavior? | Queue / Deque | PriorityQueue / ArrayDeque

Once you know the required behavior, choose an implementation based on ordering, access patterns, and other requirements.

40. Key Rules to Remember

  • List → ordered sequence, indexes, duplicates usually allowed.
  • Set → unique elements, no duplicates.
  • Queue → elements waiting for processing.
  • Deque → queue operations at both ends.
  • Map → key-value pairs with unique keys.
  • ArrayList → general-purpose List with efficient indexed access.
  • LinkedList → List + Deque/Queue behavior.
  • HashSet → unique elements, no guaranteed order.
  • TreeSet → unique elements in sorted order.
  • PriorityQueue → queue with priority/order rules.
  • HashMap → key-value mappings without guaranteed ordering.
  • TreeMap → key-value mappings with sorted keys.
  • Iterator → standard one-at-a-time traversal.
  • Comparator → custom comparison/order.
  • Collections → utility algorithms for collections.
  • Arrays → utility operations for arrays.

41. Summary

  • The Java Collections Framework provides a standard way to manage groups of objects.
  • The core collection interfaces include Collection, List, Set, Queue, Deque, SortedSet, and NavigableSet.
  • Map is part of the framework but forms a separate key-value hierarchy.
  • Generics such as List<String> provide type safety.
  • ArrayList, LinkedList, HashSet, TreeSet, PriorityQueue, HashMap, and TreeMap are important implementations.
  • Iterator provides standardized traversal, while Spliterator supports splittable traversal and parallel-processing scenarios.
  • Comparator lets you define custom ordering.
  • Collections provides standard collection algorithms such as sorting and searching.
  • Arrays provides common operations for arrays and helps bridge array-based and collection-based processing.
  • Legacy classes such as Vector, Stack, and Hashtable remain part of Java but modern collection types are generally preferred for new designs when appropriate.

Final Perspective

The most important lesson from the Collections Framework is not the names of individual classes. It is learning to choose the right interface for the behavior you need and then select an appropriate implementation.

List → sequence
Set → unique values
Queue/Deque → processing order
Map → key-value relationship