Java Collections Framework Notes

Quick Overview: JCF is like a toolbox in Java for handling groups of objects (like lists or maps). It helps you store, add, remove, and work with data easily. It started in Java version 1.2 and is mostly in the `java.util` package.

Table of Contents

Simple Image

What is Java Collections Framework?

Basic Idea

JCF gives you ready-made ways to store and manage collections (groups) of objects. It includes rules (interfaces), actual tools (classes), helpful methods (algorithms), and extra helpers.

Parts of JCF

Why Use It?

Key Features

Main Roots

Simple Example: Imagine a shopping list. JCF lets you add items, remove them, check if something is there, without worrying about how it's stored.
import java.util.ArrayList; // Import a collection class import java.util.Collection; // Import the interface Collection<String> shopping = new ArrayList<>(); // Create a collection shopping.add("Apple"); // Add item shopping.add("Banana"); System.out.println(shopping.size()); // Output: 2 (how many items)

Core Interfaces (Blueprints)

Interfaces define what you can do with collections. They build on each other.

1. Collection Interface(eg.List,Queue,Set)

What it is: The main blueprint for groups of items (elements). No order or no duplicates guaranteed here.

Key Actions (Methods):

  • add(E item): Put in a new item. Returns true if added
  • addAll(Collection other): Add everything from another group
  • remove(Object item): Take out the first matching item
  • removeAll(Collection other): Remove all items that are in the other group
  • retainAll(Collection other): Keep only items that are in both (like overlap)
  • contains(Object item): Check if item is there (true/false)
  • size(): How many items
  • isEmpty(): True if nothing inside
  • clear(): Empty it all
  • iterator(): Get a tool to loop through items
  • toArray(): Turn into a plain array

Explanation: This is basic for all non-map collections. It lets you add/remove/check without caring about order.

Collection<Integer> numbers = new ArrayList<>(); numbers.add(1); numbers.add(2); if (numbers.contains(1)) { System.out.println("Has 1"); // Output: Has 1 } numbers.remove(1); System.out.println(numbers.size()); // Output: 1

2. List Interface (Extends Collection)

What it is: An ordered group where duplicates are okay. You can access by position (index, starting from 0).

Extra Actions:

  • get(int index): Get item at position
  • set(int index, E item): Change item at position
  • add(int index, E item): Insert at specific spot
  • remove(int index): Remove from position
  • indexOf(Object item): Find first position of item (-1 if not found)
  • lastIndexOf(Object item): Find last position
  • subList(int start, int end): Get a part of the list as a view
  • listIterator(): Tool to go forward/backward

Explanation: Good when order matters, like a to-do list. You can insert anywhere, but it might shift items.

List<String> fruits = new ArrayList<>(); fruits.add("Apple"); fruits.add("Banana"); fruits.add(1, "Orange"); // Insert at index 1 System.out.println(fruits.get(1)); // Output: Orange fruits.set(0, "Grape"); // Change first item System.out.println(fruits); // Output: [Grape, Orange, Banana]

3. Set Interface (Extends Collection)

What it is: Group with no duplicates. No fixed order.

Actions: Same as Collection, but add won't add if already there (returns false).

Explanation: Uses equals() and hashCode() to check uniqueness. Great for unique items like IDs.

Sub-Blueprints:

  • SortedSet: Keeps items sorted (small to big)
    • Extra: first() (smallest), last() (biggest), headSet(E to), tailSet(E from)
  • NavigableSet: Like SortedSet but easier to find closest items
    • Extra: lower(E item) (just below), floor(E item), ceiling(E item), higher(E item)
Set<String> colors = new HashSet<>(); colors.add("Red"); colors.add("Red"); // Won't add duplicate System.out.println(colors.size()); // Output: 1

4. Queue Interface (Extends Collection)

What it is: Group for waiting items, usually first-in-first-out (FIFO, like a line).

Actions:

  • offer(E item): Add if possible (false if full)
  • poll(): Remove and get first (null if empty)
  • remove(): Remove first (error if empty)
  • peek(): See first without removing (null if empty)
  • element(): See first (error if empty)

Explanation: For tasks in order, like printing jobs.

Sub-Blueprint: Deque (Double-ended queue): Add/remove from both ends. Can act as stack (last-in-first-out, LIFO).

Queue<String> line = new LinkedList<>();
line.offer("Person1");
line.offer("Person2");
System.out.println(line.poll()); // Output: Person1 (removes first)

πŸ”’ BlockingQueue (Sub-interface of Queue)

What it is: A thread-safe queue used in concurrent programming. If queue is full, producer threads wait; if empty, consumer threads wait.

Special Blocking Methods:

  • put(E item): Waits if queue is full before inserting.
  • take(): Waits if queue is empty before removing.
  • offer(E item, long timeout, TimeUnit unit): Adds item, waits for space if needed.
  • poll(long timeout, TimeUnit unit): Removes item, waits if empty.

Common Implementations: ArrayBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue.

import java.util.concurrent.*;

BlockingQueue<String> queue = new ArrayBlockingQueue<>(2);
queue.put("Task1");
queue.put("Task2");
// queue.put("Task3"); // waits here until space available

System.out.println(queue.take()); // removes "Task1"

5. Map Interface

What it is: Not from Collection. Stores pairs: key (unique) and value.

Actions:

  • put(K key, V value): Add or update pair
  • get(Object key): Get value for key (null if none)
  • remove(Object key): Remove pair
  • containsKey(Object key), containsValue(Object value)
  • keySet(): Get all keys as Set
  • values(): Get all values as Collection
  • entrySet(): Get pairs as Set of entries
  • putAll(Map other): Add from another map
  • size(), isEmpty(), clear()

Explanation: Like a dictionary: key is word, value is meaning. Keys can't repeat.

Map<String, Integer> ages = new HashMap<>(); ages.put("Alice", 25); ages.put("Bob", 30); System.out.println(ages.get("Alice")); // Output: 25 ages.remove("Bob");

Concrete Implementations (Real Classes)

These are the actual tools you use. Here are the main classes organized by type:

List Classes

Class Name What It Does Speed (Key Actions) When to Use Thread Safe?
ArrayList Growable array. Fast to get by index. Get/Set: Fast (O(1))
Add/Remove end: Fast
Add/Remove middle: Slow (O(n))
Everyday lists, quick access No
LinkedList Chain of links. Implements List and Deque. Get/Set: Slow (O(n))
Add/Remove ends: Fast (O(1))
Add/remove often at ends (queues) No
Vector Old version of ArrayList, but safe for threads. Like ArrayList, but slower Old code or simple thread safety Yes
Stack Builds on Vector, for stacks (LIFO). Push/Pop: Fast Stacks, but better use Deque now Yes
List<Integer> nums = new ArrayList<>(); nums.add(10); nums.add(20);

Set Classes

Class Name What It Does Speed When to Use Thread Safe?
HashSet Uses hash for no order. Add/Remove/Check: Fast (O(1) average) Quick unique checks, no order No
LinkedHashSet Like HashSet, but remembers add order. Like HashSet Unique with order No
TreeSet Sorted tree. Add/Remove/Check: O(log n) Sorted uniques. Needs sort rule. No
EnumSet For enum types, very fast. All: O(1) Sets of enums No
Set<Integer> unique = new HashSet<>(); unique.add(5); unique.add(5); // Ignored

Queue/Deque Classes

Class Name What It Does Speed When to Use Thread Safe?
ArrayDeque Growable array for both ends. Faster than LinkedList. Add/Remove: Fast (O(1)) Queues or stacks No
LinkedList As above. Ends: Fast Queues No
PriorityQueue Heap for priorities (not fully sorted). Add/Remove: O(log n)
Peek: O(1)
Tasks by importance No
ConcurrentLinkedQueue Thread-safe unlimited queue. O(1) Multi-thread queues Yes
Queue<Integer> tasks = new PriorityQueue<>(); tasks.offer(3); tasks.offer(1); System.out.println(tasks.poll()); // Output: 1 (smallest first)

Map Classes

Class Name What It Does Speed When to Use Thread Safe?
HashMap Hash table, allows null. No order. Put/Get/Remove: O(1) average Everyday maps No
LinkedHashMap Like HashMap, tracks order (add or access). Like HashMap Order matters, like caches No
TreeMap Sorted tree for keys. O(log n) Sorted maps No
Hashtable Old, thread-safe, no null. Like HashMap, slower Old code Yes
ConcurrentHashMap Thread-safe, fast for many users. O(1) Multi-thread maps Yes
Map<String, String> phoneBook = new HashMap<>(); phoneBook.put("Alice", "123-456");

Iterators and Looping

List<String> items = Arrays.asList("A", "B");
Iterator<String> it = items.iterator();
while (it.hasNext()) {
  System.out.println(it.next()); // A then B
}

Comparators and Sorting

import java.util.*;

// βœ… Example 1: Using Comparable (natural order)
class Student implements Comparable {
    int id;
    String name;
    Student(int id, String name) {
        this.id = id; this.name = name;
    }
    // Natural order: by id (ascending)
    public int compareTo(Student other) {
        return this.id - other.id;
    }
    public String toString() { return id + "-" + name; }
}

// βœ… Example 2: Using Comparator (custom order)
class NameComparator implements Comparator {
    public int compare(Student s1, Student s2) {
        return s1.name.compareTo(s2.name); // sort by name
    }
}

public class Main {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add(new Student(3, "Deepak"));
        list.add(new Student(1, "Tushar"));
        list.add(new Student(2, "Shreeram"));

        // πŸ”Ή Natural sort (Comparable β†’ by id)
        Collections.sort(list);
        System.out.println("Sorted by ID (Comparable): " + list);

        // πŸ”Ή Custom sort (Comparator β†’ by name)
        Collections.sort(list, new NameComparator());
        System.out.println("Sorted by Name (Comparator): " + list);

        // πŸ”Ή Even shorter using lambda Comparator
        list.sort((a, b) -> b.id - a.id);
        System.out.println("Sorted by ID Desc (Lambda Comparator): " + list);
    }
}

Utility Classes (Helpers)

1. Collections Class

Static helpers:

List<String> words = new ArrayList<>(Arrays.asList("B", "A")); Collections.sort(words); // Now ["A", "B"]

2. Arrays Class

For plain arrays:

int[] arr = {3, 1, 2}; Arrays.sort(arr); // Now {1,2,3}

Generics in Collections

List<? extends Number> nums = new ArrayList<Integer>(); // Can read Numbers

Concurrency and Thread-Safety

Problem: Most normal collections (like ArrayList, HashMap, HashSet) are not thread-safe. If multiple threads update them at the same time, you can get data corruption or ConcurrentModificationException.

Fixes:

Explanation:

- Use synchronized wrappers for small, simple multi-threaded tasks.
- Use concurrent collections for servers, thread pools, or real-time systems where many threads read/write data at the same time.
- Fail-Fast Iterators throw errors if modified during iteration, while Fail-Safe Iterators (in concurrent collections) work on a snapshot and don’t throw errors.

Examples:

// βœ… Example 1: Synchronized Map
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Map<String, String> safeMap = Collections.synchronizedMap(new HashMap<>());
        safeMap.put("A", "Apple");
        safeMap.put("B", "Banana");

        synchronized (safeMap) { // Must lock while iterating
            for (String key : safeMap.keySet()) {
                System.out.println(key + " β†’ " + safeMap.get(key));
            }
        }
    }
}
// βœ… Example 2: ConcurrentHashMap (no need to lock manually)
import java.util.concurrent.*;

public class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<Integer, String> cmap = new ConcurrentHashMap<>();
        cmap.put(1, "Deepak");
        cmap.put(2, "Shreeram");
        cmap.put(3, "Tushar");

        // Multiple threads can safely access without explicit sync
        cmap.forEach((id, name) -> System.out.println(id + " β†’ " + name));
    }
}
// βœ… Example 3: CopyOnWriteArrayList (safe iteration even with updates)
import java.util.concurrent.*;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");

        for (String s : list) {
            System.out.println(s);
            list.add("D"); // No error, works safely
        }
        System.out.println("Final List: " + list);
    }
}

Advanced Topics

Interview Questions and Tips

Common Interview Questions

1. What is the difference between List, Set, and Map?

Answer: List: Ordered, duplicates ok. Set: No duplicates, no order (usually). Map: Key-value, unique keys.

2. When to use ArrayList vs. LinkedList?

Answer: ArrayList: Fast get by index. LinkedList: Fast add/remove at ends.

3. How does HashMap work inside?

Answer: Uses hash to find bucket, handles collisions with lists/trees.

4. What is fail-fast iterator?

Answer: Throws error if collection changes during loop.

5. Explain generics in collections.

Answer: Add type like <String> for safety.

6. How to make a collection thread-safe?

Answer: Use synchronized wrapper or concurrent classes.

7. Difference between Comparable and Comparator?

Answer: Comparable: In class itself. Comparator: Separate for custom.

8. What is PriorityQueue?

Answer: Heap for min/max priority.

9. How to sort a list?

Answer: Collections.sort(list).

10. What are views in Map (like keySet)?

Answer: Live subsets that change with map.

Tips for Interviews

  • Prepare Basics: Know interfaces and when to use each implementation (e.g., HashSet for uniqueness)
  • Code Examples: Practice writing simple code like adding to a map or sorting a list
  • Common Mistakes: Talk about overriding equals/hashCode for custom keys
  • Performance: Mention Big O (e.g., O(1) for HashMap get)
  • Modern Java: Know generics, streams, and concurrent stuff
  • Practice: Solve problems like "Implement a LRU cache" using LinkedHashMap
  • Explain Clearly: Use simple words, draw diagrams if possible
  • Edge Cases: Think about nulls, empty collections, duplicates

Quick Reference for Interviews:

  • Need order + duplicates? β†’ ArrayList
  • Need unique items? β†’ HashSet
  • Need key-value pairs? β†’ HashMap
  • Need sorting? β†’ TreeSet/TreeMap
  • Need thread safety? β†’ ConcurrentHashMap
  • Need queue/stack? β†’ ArrayDeque
  • Need priority? β†’ PriorityQueue