Collections in Java
Learn the Java Collections Framework, including List, Set, Map, Queue, Deque, ArrayList, LinkedList, HashSet, TreeSet, HashMap, iteration, sorting, and common collection operations.
What is the Collections Framework?
The Java Collections Framework provides interfaces and implementations for storing and manipulating groups of objects.
The main collection interfaces include
List, Set, Queue,
Deque, and Map.
List<String> names =
new ArrayList<>();
names.add("Amit");
names.add("Neha");
System.out.println(names);
Collection Framework Overview
Collection
│
├── List
│ ├── ArrayList
│ └── LinkedList
│
├── Set
│ ├── HashSet
│ ├── LinkedHashSet
│ └── TreeSet
│
└── Queue
├── PriorityQueue
└── Deque
└── ArrayDeque
Map
├── HashMap
├── LinkedHashMap
└── TreeMap
Map is part of the Java Collections Framework,
but it does not extend the Collection interface.
List
A List is an ordered collection that permits
duplicate elements and provides index-based access.
List<String> names =
new ArrayList<>();
names.add("Amit");
names.add("Neha");
names.add("Amit");
System.out.println(names);
[Amit, Neha, Amit]
ArrayList
ArrayList is a resizable-array implementation of
the List interface.
ArrayList<String> languages =
new ArrayList<>();
languages.add("Java");
languages.add("Python");
languages.add("C#");
System.out.println(
languages.get(0)
);
ArrayList is generally a good default when you need indexed access and frequent access by position.
Common ArrayList Operations
List<String> names =
new ArrayList<>();
names.add("Amit");
names.add("Neha");
names.add(1, "Rahul");
names.set(0, "Priya");
names.remove("Neha");
System.out.println(names);
LinkedList
LinkedList implements both
List and Deque. It can be useful
when operations at the ends are important.
LinkedList<String> names =
new LinkedList<>();
names.add("Amit");
names.addFirst("Neha");
names.addLast("Rahul");
System.out.println(names);
Set
A Set does not permit duplicate elements.
Set<String> languages =
new HashSet<>();
languages.add("Java");
languages.add("Python");
languages.add("Java");
System.out.println(languages);
The duplicate "Java" value is not added again.
HashSet
HashSet is a hash-table-based implementation of
Set. It does not guarantee iteration order.
Set<Integer> numbers =
new HashSet<>();
numbers.add(30);
numbers.add(10);
numbers.add(20);
numbers.add(10);
System.out.println(numbers);
LinkedHashSet
LinkedHashSet maintains insertion order during
iteration.
Set<String> names =
new LinkedHashSet<>();
names.add("Amit");
names.add("Neha");
names.add("Rahul");
System.out.println(names);
TreeSet
TreeSet is a sorted set implementation based on
a tree structure.
Set<Integer> numbers =
new TreeSet<>();
numbers.add(50);
numbers.add(10);
numbers.add(30);
numbers.add(20);
System.out.println(numbers);
[10, 20, 30, 50]
Queue
A Queue is commonly used when elements need to
be processed according to a particular ordering, often
FIFO.
Queue<String> queue =
new LinkedList<>();
queue.offer("A");
queue.offer("B");
queue.offer("C");
System.out.println(queue.poll());
A
PriorityQueue
PriorityQueue processes elements according to
their priority rather than simple insertion order.
Queue<Integer> numbers =
new PriorityQueue<>();
numbers.offer(30);
numbers.offer(10);
numbers.offer(20);
System.out.println(numbers.poll());
10
Deque
A Deque supports insertion and removal at both
ends of the sequence.
Deque<String> deque =
new ArrayDeque<>();
deque.addFirst("A");
deque.addLast("B");
System.out.println(
deque.removeFirst()
);
System.out.println(
deque.removeLast()
);
Map
A Map stores key-value associations. Keys are
unique within a map.
Map<Integer, String> students =
new HashMap<>();
students.put(101, "Amit");
students.put(102, "Neha");
System.out.println(
students.get(101)
);
HashMap
HashMap is a commonly used map implementation
based on hashing. It does not guarantee iteration order.
Map<String, Integer> scores =
new HashMap<>();
scores.put("Amit", 90);
scores.put("Neha", 85);
scores.put("Amit", 95);
System.out.println(
scores.get("Amit")
);
95
Adding a value with an existing key replaces the previous value associated with that key.
LinkedHashMap
LinkedHashMap maintains a predictable iteration
order, normally based on insertion order unless configured
for access order.
Map<String, Integer> scores =
new LinkedHashMap<>();
scores.put("Amit", 90);
scores.put("Neha", 85);
scores.put("Rahul", 88);
System.out.println(scores);
TreeMap
TreeMap maintains its keys in sorted order
according to their natural ordering or a supplied comparator.
Map<Integer, String> students =
new TreeMap<>();
students.put(103, "Rahul");
students.put(101, "Amit");
students.put(102, "Neha");
System.out.println(students);
Iterating Through a Collection
List<String> names =
List.of("Amit", "Neha", "Rahul");
for (String name : names) {
System.out.println(name);
}
Iterator
An Iterator provides a standard way to traverse
many collection types.
List<String> names =
new ArrayList<>();
names.add("Amit");
names.add("Neha");
names.add("Rahul");
Iterator<String> iterator =
names.iterator();
while (iterator.hasNext()) {
String name = iterator.next();
System.out.println(name);
}
Removing Elements with Iterator
An iterator can safely remove elements from the collection
during iteration using its remove() method.
List<Integer> numbers =
new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
Iterator<Integer> iterator =
numbers.iterator();
while (iterator.hasNext()) {
Integer number = iterator.next();
if (number == 20) {
iterator.remove();
}
}
Sorting Collections
The Collections.sort() method can sort a mutable
list according to natural ordering.
List<Integer> numbers =
new ArrayList<>(
List.of(50, 10, 30, 20)
);
Collections.sort(numbers);
System.out.println(numbers);
Sorting with Comparator
A Comparator allows custom ordering.
List<Integer> numbers =
new ArrayList<>(
List.of(10, 20, 30, 40)
);
numbers.sort(
Comparator.reverseOrder()
);
System.out.println(numbers);
[40, 30, 20, 10]
Iterating Through a Map
Map<String, Integer> scores =
Map.of(
"Amit", 90,
"Neha", 85
);
for (
Map.Entry<String, Integer> entry
: scores.entrySet()
) {
System.out.println(
entry.getKey()
+ " = "
+ entry.getValue()
);
}
Useful Map Methods
Map<String, Integer> scores =
new HashMap<>();
scores.put("Amit", 90);
scores.containsKey("Amit");
scores.containsValue(90);
scores.get("Amit");
scores.getOrDefault(
"Neha",
0
);
scores.remove("Amit");
getOrDefault()
getOrDefault() returns a fallback value when a
requested key is not present.
Map<String, Integer> scores =
new HashMap<>();
scores.put("Amit", 90);
int score = scores.getOrDefault(
"Neha",
0
);
System.out.println(score);
0
computeIfAbsent()
computeIfAbsent() can create and store a value
when a key does not already have a mapping.
Map<String, List<String>> groups =
new HashMap<>();
groups.computeIfAbsent(
"Java",
key -> new ArrayList<>()
).add("Amit");
System.out.println(groups);
Immutable Collection Factories
Modern Java provides convenient factory methods such as
List.of(), Set.of(), and
Map.of() for creating unmodifiable collections.
List<String> names =
List.of("Amit", "Neha");
Set<Integer> numbers =
Set.of(10, 20, 30);
Map<Integer, String> students =
Map.of(
101, "Amit",
102, "Neha"
);
add() or
remove().
Null Values
Collection implementations differ in how they handle
null. For example, HashMap permits a null key
and null values, while TreeMap's behavior depends on the
ordering configuration.
Always check the contract of the particular collection implementation when null handling matters.
Choosing the Right Collection
| Requirement | Common Choice |
|---|---|
| Indexed ordered data | ArrayList |
| Unique values | HashSet |
| Unique sorted values | TreeSet |
| Insertion-order set | LinkedHashSet |
| Key-value lookup | HashMap |
| Sorted keys | TreeMap |
| FIFO-style processing | Queue |
| Both-end operations | Deque / ArrayDeque |
Collections vs Arrays
| Feature | Array | Collection |
|---|---|---|
| Size | Fixed | Usually dynamic |
| Primitive Elements | Supported | Use wrapper types |
| Built-in Operations | Limited | Rich API |
| Generics | Array component types | Strongly integrated |
Example: Employee Management
Map<Integer, String> employees =
new HashMap<>();
employees.put(101, "Amit");
employees.put(102, "Neha");
employees.put(103, "Rahul");
for (
Map.Entry<Integer, String> entry
: employees.entrySet()
) {
System.out.println(
entry.getKey()
+ " : "
+ entry.getValue()
);
}
Performance Considerations
Different collection implementations provide different performance characteristics.
-
ArrayListprovides efficient indexed access. -
HashMapis commonly used for fast key-based lookup under typical conditions. -
TreeMapandTreeSetmaintain sorted order with logarithmic-style tree operations. - Choose based on required operations rather than assuming one collection is always fastest.
Collections Best Practices
-
Declare variables using interfaces such as
List,Set, andMapwhere practical. - Choose an implementation based on ordering, uniqueness, lookup, and update requirements.
- Use generics to maintain compile-time type safety.
- Avoid raw collection types.
- Prefer unmodifiable collections when mutation is not required.
Interview Questions
Summary
The Java Collections Framework provides reusable data structures for managing groups of objects. Important interfaces include List, Set, Queue, Deque, and Map, with implementations such as ArrayList, HashSet, TreeSet, HashMap, TreeMap, and ArrayDeque.