Skip to main content
    Courses/Java/Collections Framework

    Lesson 13 • Expert

    Collections Framework

    Master Java's powerful data structure library — the right collection choice can make your program 100x faster.

    📚 Before You Start

    You should understand:

    • Arrays (Lesson 7) — fixed-size data storage
    • OOP (Lesson 9) — classes, objects, and interfaces
    • Loops (Lesson 5) — iterating through data

    What You'll Learn

    • ✅ ArrayList — dynamic resizable arrays for ordered data
    • ✅ HashMap — key-value pairs for blazing-fast lookups
    • ✅ HashSet — unique elements with O(1) contains checks
    • ✅ LinkedList, Stack, and Queue for specialized needs
    • ✅ Iterating with for-each, iterators, and streams
    • ✅ Choosing the right collection (performance guide)

    1️⃣ Why Collections Matter

    Real-world analogy: Collections are like different types of storage containers. An ArrayList is a numbered filing cabinet — great for ordered access. A HashMap is a dictionary — look up any word instantly. A HashSet is a bag of unique marbles — quickly check "is this marble in the bag?"

    Why not just use arrays? Arrays have a fixed size. Collections resize dynamically, offer rich APIs (search, sort, filter), and provide type safety with generics.

    2️⃣ ArrayList — Your Go-To List

    Use ArrayList when you need ordered data with fast index access. It's the most commonly used collection.

    List<String> names = new ArrayList<>();
    names.add("Alice");              // add to end
    names.add("Bob");
    names.add(1, "Charlie");         // insert at index 1
    names.get(0);                    // "Alice" — O(1)
    names.set(0, "Alicia");          // replace at index
    names.remove("Bob");             // remove by value
    names.size();                    // current count
    names.contains("Charlie");      // true
    
    // Sort and iterate
    Collections.sort(names);        // alphabetical
    for (String name : names) {     // for-each
        System.out.println(name);
    }

    Performance: O(1) for get/set by index, O(n) for insert/remove in the middle.

    ArrayList Operations
    import java.util.*;
    
    public class Main {
        record Student(String name, int grade) {}
    
        public static void main(String[] args) {
            System.out.println("=== ArrayList Operations ===\n");
    
            // 1. Basic operations
            List<String> names = new ArrayList<>(List.of("Alice", "Bob", "Charlie"));
            System.out.println("1. Initial list: " + String.join(", ", names));
    
            names.add("Diana");
            System.out.println("   After add('Diana'): " + String.join(", ", names));
    
            names.add(1, "Eve");                 // insert at index 1
            System.out.println("   After add(1, 'Eve'): " + String.join(", ", names));
    
            System.out.println("   get(0): " + names.get(0));
            System.out.println("   size: " + names.size());
            System.out.println("   contains('Bob'): " + names.contains("Bob"));
    
            names.remove("Bob");
            System.out.println("   After remove('Bob'): " + String.join(", ", names));
    
            // 2. Sorting
            Collections.sort(names);
            System.out.println("\n2. Sorted: " + String.join(", ", names));
    
            // 3. Filtering with streams
            List<String> longNames = names.stream()
                .filter(n -> n.length() > 4)
                .toList();
            System.out.println("\n3. Names longer than 4 chars: " + String.join(", ", longNames));
    
            // 4. Transform with streams
            List<String> upper = names.stream()
                .map(String::toUpperCase)
                .toList();
            System.out.println("4. Uppercase: " + String.join(", ", upper));
    
            // 5. Student grade list, ranked descending
            System.out.println("\n5. Student Grade System:");
            List<Student> students = new ArrayList<>(List.of(
                new Student("Alice", 95),
                new Student("Bob", 82),
                new Student("Charlie", 91),
                new Student("Diana", 78),
                new Student("Eve", 88)
            ));
            students.sort(Comparator.comparingInt(Student::grade).reversed());
            System.out.println("   Ranked by grade:");
            for (int i = 0; i < students.size(); i++) {
                Student s = students.get(i);
                System.out.println("   " + (i + 1) + ". " + s.name() + ": " + s.grade());
            }
            double avg = students.stream().mapToInt(Student::grade).average().orElse(0);
            System.out.printf("   Average: %.1f%n", avg);
            System.out.println("   Top student: " + students.get(0).name());
        }
    }
    Output
    === ArrayList Operations ===
    
    1. Initial list: Alice, Bob, Charlie
       After add('Diana'): Alice, Bob, Charlie, Diana
       After add(1, 'Eve'): Alice, Eve, Bob, Charlie, Diana
       get(0): Alice
       size: 5
       contains('Bob'): true
       After remove('Bob'): Alice, Eve, Charlie, Diana
    
    2. Sorted: Alice, Charlie, Diana, Eve
    
    3. Names longer than 4 chars: Alice, Charlie
    
    4. Uppercase: ALICE, CHARLIE, DIANA, EVE
    
    5. Student Grade System:
       Ranked by grade:
       1. Alice: 95
       2. Charlie: 91
       3. Eve: 88
       4. Bob: 82
       5. Diana: 78
       Average: 86.8
       Top student: Alice
    This is real code — run it for free atonecompiler.com/javaor in your own editor.

    3️⃣ HashMap — Key-Value Lookups

    Analogy: Like a phone book — you look up a person's name (key) to find their number (value). You don't search page by page; you jump directly to the right entry.

    Map<String, Integer> scores = new HashMap<>();
    scores.put("Alice", 95);
    scores.put("Bob", 87);
    
    scores.get("Alice");            // 95 — O(1) average!
    scores.containsKey("Bob");      // true
    scores.getOrDefault("Diana", 0); // 0 (safe default)
    
    // Common pattern: counting frequency
    Map<String, Integer> freq = new HashMap<>();
    for (String word : words) {
        freq.put(word, freq.getOrDefault(word, 0) + 1);
    }

    4️⃣ HashSet — Unique Elements

    Use HashSet when you need to track unique items. Duplicates are silently ignored.

    Set<String> tags = new HashSet<>();
    tags.add("java");
    tags.add("oop");
    tags.add("java");     // duplicate — silently ignored!
    tags.size();          // 2
    tags.contains("java"); // true — O(1)!
    
    // Great for deduplication
    List<String> withDupes = Arrays.asList("a", "b", "a", "c", "b");
    Set<String> unique = new HashSet<>(withDupes); // {"a", "b", "c"}
    HashMap & HashSet
    import java.util.*;
    import java.util.stream.Collectors;
    
    public class Main {
        public static void main(String[] args) {
            System.out.println("=== HashMap & HashSet ===\n");
    
            // 1. HashMap — scores (LinkedHashMap keeps insertion order for printing)
            System.out.println("1. HashMap (Student Scores):");
            Map<String, Integer> scores = new LinkedHashMap<>();
            scores.put("Alice", 95);
            scores.put("Bob", 87);
            scores.put("Charlie", 92);
            scores.put("Diana", 88);
            System.out.println("   Alice: " + scores.get("Alice"));
            System.out.println("   Size: " + scores.size());
            System.out.println("   Has 'Bob': " + scores.containsKey("Bob"));
            System.out.println("   Unknown: " + scores.getOrDefault("Unknown", -1));
    
            // 2. Word frequency counter (merge is the idiomatic counting pattern)
            System.out.println("\n2. Word Frequency Counter:");
            String text = "java is great java is powerful java collections are useful collections are great";
            Map<String, Integer> freq = new HashMap<>();
            for (String w : text.split(" ")) {
                freq.merge(w, 1, Integer::sum);
            }
            freq.entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
                .forEach(e -> System.out.println("   " + e.getKey() + ": " + e.getValue()));
    
            // 3. HashSet — unique tags
            System.out.println("\n3. HashSet (Unique Tags):");
            Set<String> tags = new LinkedHashSet<>();
            tags.add("java"); tags.add("oop"); tags.add("java"); tags.add("collections");
            System.out.println("   Tags: " + String.join(", ", tags));
            System.out.println("   Size: " + tags.size() + " (duplicate 'java' was ignored!)");
    
            // 4. Deduplication
            System.out.println("\n4. Deduplication:");
            List<String> dupes = List.of("apple", "banana", "apple", "cherry", "banana", "date");
            List<String> unique = new ArrayList<>(new LinkedHashSet<>(dupes));
            System.out.println("   Before: " + String.join(", ", dupes));
            System.out.println("   After: " + String.join(", ", unique));
    
            // 5. Group students by grade
            System.out.println("\n5. Group By Grade:");
            record Student(String name, String grade) {}
            List<Student> students = List.of(
                new Student("Alice", "A"), new Student("Bob", "B"),
                new Student("Charlie", "A"), new Student("Diana", "B"),
                new Student("Eve", "A")
            );
            Map<String, List<String>> grouped = students.stream()
                .collect(Collectors.groupingBy(Student::grade, TreeMap::new,
                         Collectors.mapping(Student::name, Collectors.toList())));
            grouped.forEach((grade, names) ->
                System.out.println("   Grade " + grade + ": " + String.join(", ", names)));
        }
    }
    Output
    === HashMap & HashSet ===
    
    1. HashMap (Student Scores):
       Alice: 95
       Size: 4
       Has 'Bob': true
       Unknown: -1
    
    2. Word Frequency Counter:
       java: 3
       is: 2
       are: 2
       great: 2
       collections: 2
       powerful: 1
       useful: 1
    
    3. HashSet (Unique Tags):
       Tags: java, oop, collections
       Size: 3 (duplicate 'java' was ignored!)
    
    4. Deduplication:
       Before: apple, banana, apple, cherry, banana, date
       After: apple, banana, cherry, date
    
    5. Group By Grade:
       Grade A: Alice, Charlie, Eve
       Grade B: Bob, Diana
    This is real Java — run it free at onecompiler.com/java. The frequency-counter rows for words that share a count (e.g. is/are/great/collections) may print in a different order, since ties aren't ordered.

    5️⃣ Which Collection Should I Use?

    NeedUseWhy
    Ordered list, read by indexArrayListO(1) get, auto-resize
    Frequent insert/remove at endsLinkedListO(1) add/remove at head/tail
    Key → value mappingHashMapO(1) lookup by key
    Sorted key → valueTreeMapKeys always sorted
    Unique elements onlyHashSetO(1) contains check
    LIFO (undo, backtracking)Deque/Stackpush/pop O(1)
    FIFO (task queue, BFS)Queue/LinkedListoffer/poll O(1)

    Default choice: Start with ArrayList for lists and HashMap for key-value pairs.

    6️⃣ Common Beginner Mistakes

    ❌ Mistake 1: Modifying a collection while iterating

    // CRASHES with ConcurrentModificationException!
    for (String s : list) {
        if (s.equals("remove")) list.remove(s);
    }
    
    // CORRECT: use removeIf (Java 8+)
    list.removeIf(s -> s.equals("remove"));

    ❌ Mistake 2: Using raw types (no generics)

    List list = new ArrayList();     // BAD — no type safety
    List<String> list = new ArrayList<>(); // GOOD

    ❌ Mistake 3: Not overriding hashCode() with HashMap keys

    If you override equals(), you must also override hashCode().

    Stack, Queue & Practical Patterns
    import java.util.*;
    
    public class Main {
        record Task(String name, int priority) {}
    
        public static void main(String[] args) {
            System.out.println("=== Stack & Queue ===\n");
    
            // 1. Stack (LIFO) via Deque — preferred over the legacy Stack class
            System.out.println("1. Browser History Stack:");
            Deque<String> history = new ArrayDeque<>();
            history.push("google.com");
            history.push("github.com");
            history.push("stackoverflow.com");
            System.out.println("   Current page: " + history.peek());
            System.out.println("   Back (pop): " + history.pop());
            System.out.println("   Now on: " + history.peek());
    
            // 2. Undo stack
            System.out.println("\n2. Text Editor Undo:");
            Deque<String> undoStack = new ArrayDeque<>();
            StringBuilder text = new StringBuilder();
            for (String chars : new String[]{"Hello", " World", "!"}) {
                undoStack.push(text.toString());
                text.append(chars);
                System.out.println("   Type '" + chars + "' -> '" + text + "'");
            }
            for (int i = 0; i < 2; i++) {
                text = new StringBuilder(undoStack.pop());
                System.out.println("   Undo -> '" + text + "'");
            }
            System.out.println("   Final: '" + text + "'");
    
            // 3. Queue (FIFO)
            System.out.println("\n3. Print Queue:");
            Queue<String> printQueue = new LinkedList<>();
            printQueue.offer("Report.pdf");
            printQueue.offer("Photo.jpg");
            printQueue.offer("Resume.docx");
            System.out.println("   Queue: " + String.join(", ", printQueue));
            while (!printQueue.isEmpty()) {
                System.out.println("   Printing: " + printQueue.poll());
            }
    
            // 4. Practical: priority-ordered task scheduler
            System.out.println("\n4. Task Scheduler:");
            PriorityQueue<Task> tasks = new PriorityQueue<>(Comparator.comparingInt(Task::priority));
            tasks.offer(new Task("Build UI", 2));
            tasks.offer(new Task("Write tests", 1));
            tasks.offer(new Task("Deploy", 3));
            System.out.println("   Tasks (by priority):");
            int completed = 0;
            while (!tasks.isEmpty()) {
                Task task = tasks.poll();
                System.out.println("   - " + task.name() + " (priority " + task.priority() + ")");
                completed++;
            }
            System.out.println("   Completed: " + completed + " tasks");
        }
    }
    Output
    === Stack & Queue ===
    
    1. Browser History Stack:
       Current page: stackoverflow.com
       Back (pop): stackoverflow.com
       Now on: github.com
    
    2. Text Editor Undo:
       Type 'Hello' -> 'Hello'
       Type ' World' -> 'Hello World'
       Type '!' -> 'Hello World!'
       Undo -> 'Hello World'
       Undo -> 'Hello'
       Final: 'Hello'
    
    3. Print Queue:
       Queue: Report.pdf, Photo.jpg, Resume.docx
       Printing: Report.pdf
       Printing: Photo.jpg
       Printing: Resume.docx
    
    4. Task Scheduler:
       Tasks (by priority):
       - Write tests (priority 1)
       - Build UI (priority 2)
       - Deploy (priority 3)
       Completed: 3 tasks
    This is real code — run it for free atonecompiler.com/javaor in your own editor.

    📋 Quick Reference

    CollectionKey MethodsComplexity
    ArrayListadd, get, set, remove, sizeO(1) get, O(n) insert
    LinkedListaddFirst, addLast, pollO(1) ends, O(n) middle
    HashMapput, get, containsKey, removeO(1) average
    TreeMapput, get, firstKey, lastKeyO(log n) sorted
    HashSetadd, contains, removeO(1) average
    Stack/Dequepush, pop, peekO(1)

    🎉 Lesson Complete!

    You now know how to use Java's core collections — ArrayList, HashMap, HashSet, Stack, and Queue — and how to choose the right one based on your data access patterns.

    Next up: Generics — write type-safe, reusable code that works with any data type.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service

    Install LearnCodingFast

    Learn faster with the app on your home screen.