Skip to main content
  1. Resources/
  2. Study Materials/
  3. Information & Communication Technology Engineering/
  4. ICT Semester 4/
  5. Java Programming (4343203)/

17 mins· ·
Milav Dabgar
Author
Milav Dabgar
Experienced lecturer in the electrical and electronic manufacturing industry. Skilled in Embedded Systems, Image Processing, Data Science, MATLAB, Python, STM32. Strong education professional with a Master’s degree in Communication Systems Engineering from L.D. College of Engineering - Ahmedabad.
Lecture 17: Java Collections Framework | Java Programming (4343203)

Java Collections Framework

Java Programming (4343203)

Lecture 17

Unit 4: Advanced Java - Data Structures
GTU Computer Engineering Semester 4

Learning Objectives

  • Understand the Java Collections Framework hierarchy
  • Master List interface implementations (ArrayList, LinkedList, Vector)
  • Learn Set interface and implementations (HashSet, TreeSet)
  • Implement Map interface (HashMap, TreeMap, LinkedHashMap)
  • Use iterators and enhanced for loops effectively
  • Apply Comparable and Comparator for custom sorting
Focus: Efficient data storage, manipulation, and retrieval using Java's built-in collection classes.

Java Collections Framework Overview

What is Collections Framework?

  • Unified architecture for storing/manipulating groups of objects
  • Provides interfaces, implementations, and algorithms
  • Reduces programming effort and increases performance
  • Enables interoperability among unrelated APIs

Key Benefits

  • Consistency: Common interface across collections
  • Performance: Optimized implementations
  • Interoperability: Standard interfaces
  • Maintainability: Well-tested, documented APIs
Collection Interface Hierarchy:

Collection<E>
├── List<E>
│ ├── ArrayList<E>
│ ├── LinkedList<E>
│ └── Vector<E>
├── Set<E>
│ ├── HashSet<E>
│ ├── LinkedHashSet<E>
│ └── TreeSet<E>
└── Queue<E>
├── PriorityQueue<E>
└── LinkedList<E>

Map<K,V> (separate hierarchy)
├── HashMap<K,V>
├── LinkedHashMap<K,V>
└── TreeMap<K,V>

Core Collection Interfaces

InterfaceDescriptionKey FeaturesCommon Implementations
Collection<E>Root interfaceBasic operations: add, remove, containsN/A (abstract)
List<E>Ordered collection with duplicatesIndex-based access, positional operationsArrayList, LinkedList, Vector
Set<E>Collection with no duplicatesMathematical set operationsHashSet, TreeSet, LinkedHashSet
Queue<E>Collection for holding elements before processingFIFO operations: offer, poll, peekLinkedList, PriorityQueue
Map<K,V>Key-value pair mappingUnique keys, efficient lookupsHashMap, TreeMap, LinkedHashMap

List Interface - ArrayList

ArrayList Characteristics

  • Resizable array implementation
  • Allows duplicates and null values
  • Maintains insertion order
  • Random access (O(1) for get/set)
  • Not synchronized (not thread-safe)

Performance Characteristics

  • Access: O(1)
  • Insert/Delete at end: O(1) amortized
  • Insert/Delete at middle: O(n)
  • Search: O(n)

import java.util.*;

public class ArrayListDemo {
    public static void main(String[] args) {
        // Create ArrayList
        List fruits = new ArrayList<>();
        
        // Adding elements
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Cherry");
        fruits.add(1, "Orange"); // Insert at index
        
        System.out.println("Fruits: " + fruits);
        
        // Accessing elements
        System.out.println("First fruit: " + fruits.get(0));
        System.out.println("Size: " + fruits.size());
        
        // Modifying elements
        fruits.set(2, "Mango");
        System.out.println("After modification: " + fruits);
        
        // Searching
        boolean hasApple = fruits.contains("Apple");
        int index = fruits.indexOf("Banana");
        System.out.println("Has Apple: " + hasApple);
        System.out.println("Banana index: " + index);
        
        // Removing elements
        fruits.remove("Orange");
        fruits.remove(0); // Remove by index
        System.out.println("After removal: " + fruits);
        
        // Converting to array
        String[] fruitArray = fruits.toArray(new String[0]);
        System.out.println("Array: " + Arrays.toString(fruitArray));
    }
}
                        

LinkedList Implementation


import java.util.*;

public class LinkedListDemo {
    public static void main(String[] args) {
        // LinkedList as List and Deque
        LinkedList numbers = new LinkedList<>();
        
        // Adding elements
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.addFirst(5);  // Add to beginning
        numbers.addLast(40);  // Add to end
        
        System.out.println("LinkedList: " + numbers);
        
        // Accessing elements
        System.out.println("First: " + numbers.getFirst());
        System.out.println("Last: " + numbers.getLast());
        System.out.println("Element at index 2: " + numbers.get(2));
        
        // Queue operations
        numbers.offer(50);    // Add to tail (same as addLast)
        int head = numbers.poll(); // Remove and return head
        System.out.println("After poll: " + numbers + ", removed: " + head);
        
        // Stack operations
        numbers.push(1);      // Add to front (same as addFirst)
        int top = numbers.pop(); // Remove and return first
        System.out.println("After pop: " + numbers + ", removed: " + top);
        
        // Iteration
        System.out.print("Forward iteration: ");
        Iterator iterator = numbers.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();
        
        System.out.print("Reverse iteration: ");
        Iterator descIterator = numbers.descendingIterator();
        while (descIterator.hasNext()) {
            System.out.print(descIterator.next() + " ");
        }
        System.out.println();
        
        // Performance comparison method
        compareListPerformance();
    }
    
    private static void compareListPerformance() {
        final int SIZE = 100000;
        
        System.out.println("\n=== Performance Comparison ===");
        
        // ArrayList performance
        long start = System.currentTimeMillis();
        List arrayList = new ArrayList<>();
        for (int i = 0; i < SIZE; i++) {
            arrayList.add(i);
        }
        long arrayListTime = System.currentTimeMillis() - start;
        
        // LinkedList performance
        start = System.currentTimeMillis();
        List linkedList = new LinkedList<>();
        for (int i = 0; i < SIZE; i++) {
            linkedList.add(i);
        }
        long linkedListTime = System.currentTimeMillis() - start;
        
        System.out.printf("ArrayList add time: %d ms%n", arrayListTime);
        System.out.printf("LinkedList add time: %d ms%n", linkedListTime);
        
        // Random access performance
        start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            arrayList.get(SIZE / 2);
        }
        long arrayListAccess = System.currentTimeMillis() - start;
        
        start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            linkedList.get(SIZE / 2);
        }
        long linkedListAccess = System.currentTimeMillis() - start;
        
        System.out.printf("ArrayList random access time: %d ms%n", arrayListAccess);
        System.out.printf("LinkedList random access time: %d ms%n", linkedListAccess);
    }
}
                

Set Interface - HashSet and TreeSet

HashSet Characteristics

  • Hash table implementation
  • No duplicates, allows one null
  • No guaranteed order
  • O(1) average time for basic operations

import java.util.*;

// HashSet Demo
Set hashSet = new HashSet<>();
hashSet.add("Java");
hashSet.add("Python");
hashSet.add("C++");
hashSet.add("Java"); // Duplicate ignored

System.out.println("HashSet: " + hashSet);
// Output order is unpredictable

// Common operations
boolean hasJava = hashSet.contains("Java");
int size = hashSet.size();
hashSet.remove("C++");

System.out.println("Contains Java: " + hasJava);
System.out.println("Size: " + size);
                        

TreeSet Characteristics

  • Red-Black tree implementation
  • Sorted set (natural ordering or Comparator)
  • No duplicates, no null values
  • O(log n) time for basic operations

// TreeSet Demo
Set treeSet = new TreeSet<>();
treeSet.add(30);
treeSet.add(10);
treeSet.add(20);
treeSet.add(40);

System.out.println("TreeSet: " + treeSet);
// Output: [10, 20, 30, 40] (sorted)

// NavigableSet operations
TreeSet numbers = (TreeSet) treeSet;
System.out.println("First: " + numbers.first());
System.out.println("Last: " + numbers.last());
System.out.println("Higher than 25: " + numbers.higher(25));
System.out.println("Lower than 25: " + numbers.lower(25));

// Subset operations
SortedSet subset = numbers.subSet(15, 35);
System.out.println("Subset [15,35): " + subset);
                        

Map Interface - HashMap


import java.util.*;

public class HashMapDemo {
    public static void main(String[] args) {
        // Create HashMap
        Map studentGrades = new HashMap<>();
        
        // Adding key-value pairs
        studentGrades.put("Alice", 85);
        studentGrades.put("Bob", 92);
        studentGrades.put("Charlie", 78);
        studentGrades.put("Diana", 96);
        
        System.out.println("Student grades: " + studentGrades);
        
        // Accessing values
        int aliceGrade = studentGrades.get("Alice");
        System.out.println("Alice's grade: " + aliceGrade);
        
        // Check if key exists
        boolean hasEve = studentGrades.containsKey("Eve");
        boolean hasGrade90 = studentGrades.containsValue(90);
        System.out.println("Has Eve: " + hasEve);
        System.out.println("Has grade 90: " + hasGrade90);
        
        // Updating values
        studentGrades.put("Alice", 88); // Update Alice's grade
        studentGrades.putIfAbsent("Eve", 82); // Add only if key doesn't exist
        
        System.out.println("After updates: " + studentGrades);
        
        // Iteration methods
        System.out.println("\n=== Iteration Methods ===");
        
        // 1. Iterate over keys
        System.out.print("Students: ");
        for (String student : studentGrades.keySet()) {
            System.out.print(student + " ");
        }
        System.out.println();
        
        // 2. Iterate over values
        System.out.print("Grades: ");
        for (Integer grade : studentGrades.values()) {
            System.out.print(grade + " ");
        }
        System.out.println();
        
        // 3. Iterate over entries
        System.out.println("Student-Grade pairs:");
        for (Map.Entry entry : studentGrades.entrySet()) {
            System.out.println(entry.getKey() + " -> " + entry.getValue());
        }
        
        // 4. Java 8 forEach with lambda
        System.out.println("Using forEach with lambda:");
        studentGrades.forEach((student, grade) -> 
            System.out.println(student + " scored " + grade)
        );
        
        // Advanced operations
        demonstrateAdvancedMapOperations(studentGrades);
    }
    
    private static void demonstrateAdvancedMapOperations(Map grades) {
        System.out.println("\n=== Advanced Map Operations ===");
        
        // Compute operations (Java 8+)
        grades.compute("Alice", (key, value) -> value + 2); // Add 2 to Alice's grade
        System.out.println("After compute: " + grades.get("Alice"));
        
        // Merge operation
        grades.merge("Bob", 5, Integer::sum); // Add 5 to Bob's grade
        System.out.println("After merge: " + grades.get("Bob"));
        
        // Replace operations
        grades.replace("Charlie", 78, 80); // Replace only if current value is 78
        grades.replaceAll((student, grade) -> Math.max(grade, 80)); // Ensure minimum grade of 80
        
        System.out.println("After replacements: " + grades);
        
        // Remove operations
        grades.remove("Diana", 96); // Remove only if key-value pair matches
        System.out.println("After conditional remove: " + grades);
    }
}
                

TreeMap and LinkedHashMap

TreeMap Example


import java.util.*;

// TreeMap - sorted by keys
TreeMap capitals = new TreeMap<>();
capitals.put("USA", "Washington DC");
capitals.put("India", "New Delhi");
capitals.put("China", "Beijing");
capitals.put("Brazil", "Brasília");

System.out.println("TreeMap (sorted by keys):");
capitals.forEach((country, capital) -> 
    System.out.println(country + " -> " + capital)
);

// NavigableMap operations
System.out.println("First entry: " + capitals.firstEntry());
System.out.println("Last key: " + capitals.lastKey());
System.out.println("Higher key than 'India': " + 
                   capitals.higherKey("India"));

// Subset operations
SortedMap subset = 
    capitals.subMap("Brazil", "USA");
System.out.println("Subset [Brazil, USA): " + subset);

// Custom comparator
TreeMap wordLengths = 
    new TreeMap<>((a, b) -> Integer.compare(a.length(), b.length()));
wordLengths.put("elephant", 8);
wordLengths.put("cat", 3);
wordLengths.put("butterfly", 9);

System.out.println("Sorted by length: " + wordLengths);
                        

LinkedHashMap Example


import java.util.*;

// LinkedHashMap - maintains insertion order
LinkedHashMap languages = 
    new LinkedHashMap<>();
languages.put("Java", "Object-oriented");
languages.put("Python", "Interpreted");
languages.put("C++", "Compiled");
languages.put("JavaScript", "Scripting");

System.out.println("LinkedHashMap (insertion order):");
languages.forEach((lang, type) -> 
    System.out.println(lang + " -> " + type)
);

// LRU Cache using LinkedHashMap
LinkedHashMap lruCache = 
    new LinkedHashMap(16, 0.75f, true) {
    
    @Override
    protected boolean removeEldestEntry(
        Map.Entry eldest) {
        return size() > 3; // Max 3 entries
    }
};

// Test LRU behavior
lruCache.put("A", 1);
lruCache.put("B", 2);
lruCache.put("C", 3);
System.out.println("Initial: " + lruCache);

lruCache.get("A"); // Access A (moves to end)
lruCache.put("D", 4); // Should remove B
System.out.println("After access and insert: " + lruCache);
                        

Iterators and Enhanced For Loop


import java.util.*;

public class IteratorDemo {
    public static void main(String[] args) {
        List colors = Arrays.asList("Red", "Green", "Blue", "Yellow", "Orange");
        
        System.out.println("=== Different Iteration Methods ===");
        
        // 1. Enhanced for loop (for-each)
        System.out.print("Enhanced for loop: ");
        for (String color : colors) {
            System.out.print(color + " ");
        }
        System.out.println();
        
        // 2. Iterator
        System.out.print("Iterator: ");
        Iterator iterator = colors.iterator();
        while (iterator.hasNext()) {
            String color = iterator.next();
            System.out.print(color + " ");
        }
        System.out.println();
        
        // 3. ListIterator (bidirectional)
        System.out.print("ListIterator (reverse): ");
        ListIterator listIterator = colors.listIterator(colors.size());
        while (listIterator.hasPrevious()) {
            String color = listIterator.previous();
            System.out.print(color + " ");
        }
        System.out.println();
        
        // 4. Traditional for loop with index
        System.out.print("Traditional for loop: ");
        for (int i = 0; i < colors.size(); i++) {
            System.out.print(colors.get(i) + " ");
        }
        System.out.println();
        
        // 5. Java 8 Streams
        System.out.print("Stream forEach: ");
        colors.stream().forEach(color -> System.out.print(color + " "));
        System.out.println();
        
        // Safe iteration with modification
        demonstrateSafeIteration();
    }
    
    private static void demonstrateSafeIteration() {
        System.out.println("\n=== Safe Iteration with Modification ===");
        
        List numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
        
        // UNSAFE: ConcurrentModificationException
        try {
            for (Integer num : numbers) {
                if (num % 2 == 0) {
                    numbers.remove(num); // This will throw exception
                }
            }
        } catch (ConcurrentModificationException e) {
            System.out.println("ConcurrentModificationException caught!");
        }
        
        // SAFE: Using Iterator.remove()
        numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
        Iterator iter = numbers.iterator();
        while (iter.hasNext()) {
            Integer num = iter.next();
            if (num % 2 == 0) {
                iter.remove(); // Safe removal
            }
        }
        System.out.println("After safe removal of even numbers: " + numbers);
        
        // SAFE: Using removeIf (Java 8+)
        numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
        numbers.removeIf(num -> num % 2 == 0);
        System.out.println("Using removeIf: " + numbers);
        
        // ListIterator for bidirectional traversal and modification
        numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
        ListIterator listIter = numbers.listIterator();
        
        while (listIter.hasNext()) {
            Integer num = listIter.next();
            if (num == 3) {
                listIter.set(30); // Replace 3 with 30
                listIter.add(35); // Add 35 after current element
            }
        }
        System.out.println("After ListIterator modifications: " + numbers);
    }
}
                

Sorting with Comparable and Comparator


import java.util.*;

// Student class implementing Comparable
class Student implements Comparable {
    private String name;
    private int age;
    private double gpa;
    
    public Student(String name, int age, double gpa) {
        this.name = name;
        this.age = age;
        this.gpa = gpa;
    }
    
    // Natural ordering by name
    @Override
    public int compareTo(Student other) {
        return this.name.compareTo(other.name);
    }
    
    @Override
    public String toString() {
        return String.format("%s(age=%d, gpa=%.2f)", name, age, gpa);
    }
    
    // Getters
    public String getName() { return name; }
    public int getAge() { return age; }
    public double getGpa() { return gpa; }
}

public class SortingDemo {
    public static void main(String[] args) {
        List students = Arrays.asList(
            new Student("Alice", 20, 3.8),
            new Student("Bob", 19, 3.6),
            new Student("Charlie", 21, 3.9),
            new Student("Diana", 20, 3.7)
        );
        
        System.out.println("Original list: " + students);
        
        // 1. Natural sorting using Comparable (by name)
        Collections.sort(students);
        System.out.println("Sorted by name: " + students);
        
        // 2. Custom sorting using Comparator - by age
        students.sort(Comparator.comparingInt(Student::getAge));
        System.out.println("Sorted by age: " + students);
        
        // 3. Sort by GPA (descending)
        students.sort(Comparator.comparingDouble(Student::getGpa).reversed());
        System.out.println("Sorted by GPA (descending): " + students);
        
        // 4. Multiple criteria sorting
        students.sort(Comparator.comparingInt(Student::getAge)
                               .thenComparing(Student::getName));
        System.out.println("Sorted by age, then name: " + students);
        
        // 5. Complex comparator with lambda
        students.sort((s1, s2) -> {
            int ageCompare = Integer.compare(s1.getAge(), s2.getAge());
            if (ageCompare != 0) return ageCompare;
            return Double.compare(s2.getGpa(), s1.getGpa()); // GPA descending
        });
        System.out.println("Sorted by age, then GPA desc: " + students);
        
        // Demonstrate with TreeSet (sorted set)
        demonstrateSortedSet();
        
        // Demonstrate with TreeMap (sorted map)
        demonstrateSortedMap();
    }
}
                

Sorted Collections Demonstration


    private static void demonstrateSortedSet() {
        System.out.println("\n=== TreeSet with Custom Comparator ===");
        
        // TreeSet with custom comparator (by GPA descending)
        TreeSet studentsByGpa = new TreeSet<>(
            Comparator.comparingDouble(Student::getGpa).reversed()
        );
        
        studentsByGpa.add(new Student("Alice", 20, 3.8));
        studentsByGpa.add(new Student("Bob", 19, 3.6));
        studentsByGpa.add(new Student("Charlie", 21, 3.9));
        studentsByGpa.add(new Student("Diana", 20, 3.7));
        
        System.out.println("Students by GPA (desc): " + studentsByGpa);
        
        // NavigableSet operations
        System.out.println("Highest GPA student: " + studentsByGpa.first());
        System.out.println("Lowest GPA student: " + studentsByGpa.last());
        
        Student threshold = new Student("", 0, 3.7);
        SortedSet highPerformers = studentsByGpa.headSet(threshold);
        System.out.println("Students with GPA > 3.7: " + highPerformers);
    }
    
    private static void demonstrateSortedMap() {
        System.out.println("\n=== TreeMap with Custom Comparator ===");
        
        // TreeMap sorted by key length, then alphabetically
        TreeMap wordFreq = new TreeMap<>(
            Comparator.comparingInt(String::length)
                      .thenComparing(String::compareTo)
        );
        
        wordFreq.put("apple", 5);
        wordFreq.put("cat", 3);
        wordFreq.put("elephant", 2);
        wordFreq.put("dog", 4);
        wordFreq.put("butterfly", 1);
        
        System.out.println("Words by length, then alphabetically:");
        wordFreq.forEach((word, freq) -> 
            System.out.printf("%-10s: %d%n", word, freq)
        );
        
        // NavigableMap operations
        System.out.println("First entry: " + wordFreq.firstEntry());
        System.out.println("Words longer than 'dog': " + wordFreq.tailMap("dog", false));
    }

// Additional utility class for complex sorting
class StudentComparators {
    // Static comparators for different sorting criteria
    public static final Comparator BY_NAME = 
        Comparator.comparing(Student::getName);
    
    public static final Comparator BY_AGE = 
        Comparator.comparingInt(Student::getAge);
    
    public static final Comparator BY_GPA = 
        Comparator.comparingDouble(Student::getGpa);
    
    // Composite comparators
    public static final Comparator BY_AGE_THEN_NAME = 
        BY_AGE.thenComparing(BY_NAME);
    
    public static final Comparator BY_GPA_DESC_THEN_NAME = 
        BY_GPA.reversed().thenComparing(BY_NAME);
    
    // Custom comparator for grade classification
    public static final Comparator BY_GRADE_CLASSIFICATION = (s1, s2) -> {
        String grade1 = getGradeClassification(s1.getGpa());
        String grade2 = getGradeClassification(s2.getGpa());
        int gradeCompare = grade1.compareTo(grade2);
        return gradeCompare != 0 ? gradeCompare : s1.getName().compareTo(s2.getName());
    };
    
    private static String getGradeClassification(double gpa) {
        if (gpa >= 3.8) return "A";
        else if (gpa >= 3.5) return "B";
        else if (gpa >= 3.0) return "C";
        else return "D";
    }
}
                

GTU Previous Year Question (Summer 2022)

Q: Write a Java program to demonstrate the use of ArrayList, HashMap, and TreeSet. The program should perform operations like adding, removing, searching, and iterating through elements. Also compare the performance characteristics of these collections.

Solution:


import java.util.*;

public class CollectionsComparison {
    private static final int DATA_SIZE = 50000;
    
    public static void main(String[] args) {
        System.out.println("=== Java Collections Framework Demonstration ===\n");
        
        // Demonstrate ArrayList
        demonstrateArrayList();
        
        // Demonstrate HashMap
        demonstrateHashMap();
        
        // Demonstrate TreeSet
        demonstrateTreeSet();
        
        // Performance comparison
        performanceComparison();
    }
    
    private static void demonstrateArrayList() {
        System.out.println("--- ArrayList Demonstration ---");
        
        ArrayList books = new ArrayList<>();
        
        // Adding elements
        books.add("Java: The Complete Reference");
        books.add("Effective Java");
        books.add("Clean Code");
        books.add("Design Patterns");
        books.add(1, "Head First Java"); // Insert at specific position
        
        System.out.println("Books after adding: " + books);
        System.out.println("Size: " + books.size());
        
        // Accessing elements
        System.out.println("First book: " + books.get(0));
        System.out.println("Last book: " + books.get(books.size() - 1));
        
        // Searching
        boolean hasCleanCode = books.contains("Clean Code");
        int index = books.indexOf("Effective Java");
        System.out.println("Contains 'Clean Code': " + hasCleanCode);
        System.out.println("Index of 'Effective Java': " + index);
        
        // Modifying elements
        books.set(2, "Spring in Action");
        System.out.println("After modification: " + books);
        
        // Iteration methods
        System.out.print("Enhanced for loop: ");
        for (String book : books) {
            System.out.print("[" + book.substring(0, Math.min(book.length(), 10)) + "...] ");
        }
        System.out.println();
        
        System.out.print("Iterator: ");
        Iterator iter = books.iterator();
        while (iter.hasNext()) {
            String book = iter.next();
            System.out.print("[" + book.substring(0, Math.min(book.length(), 10)) + "...] ");
        }
        System.out.println();
        
        // Removing elements
        books.remove("Design Patterns");
        books.remove(0); // Remove by index
        System.out.println("After removal: " + books);
        
        // Bulk operations
        List newBooks = Arrays.asList("Spring Boot", "Microservices", "Docker");
        books.addAll(newBooks);
        System.out.println("After adding all: " + books);
        
        // Sorting
        Collections.sort(books);
        System.out.println("After sorting: " + books);
        
        System.out.println();
    }
}
                

HashMap Demonstration:


    private static void demonstrateHashMap() {
        System.out.println("--- HashMap Demonstration ---");
        
        HashMap productPrices = new HashMap<>();
        
        // Adding key-value pairs
        productPrices.put("Laptop", 999.99);
        productPrices.put("Smartphone", 699.99);
        productPrices.put("Tablet", 399.99);
        productPrices.put("Headphones", 199.99);
        productPrices.put("Keyboard", 79.99);
        
        System.out.println("Product prices: " + productPrices);
        System.out.println("Size: " + productPrices.size());
        
        // Accessing values
        Double laptopPrice = productPrices.get("Laptop");
        System.out.println("Laptop price: $" + laptopPrice);
        
        // Checking existence
        boolean hasSmartphone = productPrices.containsKey("Smartphone");
        boolean hasPrice500 = productPrices.containsValue(500.0);
        System.out.println("Has Smartphone: " + hasSmartphone);
        System.out.println("Has price $500: " + hasPrice500);
        
        // Updating values
        productPrices.put("Laptop", 899.99); // Update existing
        productPrices.putIfAbsent("Mouse", 29.99); // Add if not present
        System.out.println("After updates: " + productPrices);
        
        // Iteration methods
        System.out.println("Iteration methods:");
        
        // 1. Key set iteration
        System.out.print("Keys: ");
        for (String product : productPrices.keySet()) {
            System.out.print(product + " ");
        }
        System.out.println();
        
        // 2. Values iteration
        System.out.print("Values: $");
        for (Double price : productPrices.values()) {
            System.out.print(price + " $");
        }
        System.out.println();
        
        // 3. Entry set iteration
        System.out.println("Product-Price pairs:");
        for (Map.Entry entry : productPrices.entrySet()) {
            System.out.printf("  %-12s: $%.2f%n", entry.getKey(), entry.getValue());
        }
        
        // 4. Java 8 forEach
        System.out.println("Using forEach with lambda:");
        productPrices.forEach((product, price) -> 
            System.out.printf("  %s costs $%.2f%n", product, price)
        );
        
        // Advanced operations (Java 8+)
        productPrices.compute("Laptop", (key, value) -> value * 0.9); // 10% discount
        productPrices.merge("Tablet", 50.0, Double::sum); // Add $50
        System.out.println("After compute and merge: " + productPrices);
        
        // Removing elements
        productPrices.remove("Keyboard");
        productPrices.remove("Mouse", 29.99); // Remove only if value matches
        System.out.println("After removal: " + productPrices);
        
        System.out.println();
    }
                

TreeSet Demonstration:


    private static void demonstrateTreeSet() {
        System.out.println("--- TreeSet Demonstration ---");
        
        TreeSet scores = new TreeSet<>();
        
        // Adding elements (automatically sorted)
        scores.add(85);
        scores.add(92);
        scores.add(78);
        scores.add(96);
        scores.add(82);
        scores.add(92); // Duplicate - will be ignored
        
        System.out.println("Scores (sorted): " + scores);
        System.out.println("Size: " + scores.size());
        
        // Basic operations
        boolean hasScore90 = scores.contains(90);
        System.out.println("Contains score 90: " + hasScore90);
        
        // NavigableSet operations
        System.out.println("First (lowest) score: " + scores.first());
        System.out.println("Last (highest) score: " + scores.last());
        System.out.println("Score higher than 85: " + scores.higher(85));
        System.out.println("Score lower than 85: " + scores.lower(85));
        System.out.println("Ceiling of 86: " + scores.ceiling(86));
        System.out.println("Floor of 86: " + scores.floor(86));
        
        // Subset operations
        SortedSet passedScores = scores.tailSet(80); // >= 80
        System.out.println("Passed scores (>= 80): " + passedScores);
        
        SortedSet excellentScores = scores.headSet(95); // < 95
        System.out.println("Excellent scores (< 95): " + excellentScores);
        
        SortedSet goodScores = scores.subSet(80, 90); // [80, 90)
        System.out.println("Good scores [80, 90): " + goodScores);
        
        // Iteration
        System.out.print("Forward iteration: ");
        for (Integer score : scores) {
            System.out.print(score + " ");
        }
        System.out.println();
        
        System.out.print("Reverse iteration: ");
        Iterator descIter = scores.descendingIterator();
        while (descIter.hasNext()) {
            System.out.print(descIter.next() + " ");
        }
        System.out.println();
        
        // Removing elements
        scores.pollFirst(); // Remove and return first
        scores.pollLast();  // Remove and return last
        scores.remove(85);  // Remove specific element
        System.out.println("After removals: " + scores);
        
        // TreeSet with custom comparator
        TreeSet words = new TreeSet<>(
            Comparator.comparing(String::length)
                      .thenComparing(String::compareToIgnoreCase)
        );
        
        words.addAll(Arrays.asList("elephant", "cat", "butterfly", "dog", "ant"));
        System.out.println("Words sorted by length then alphabetically: " + words);
        
        System.out.println();
    }
                

Performance Comparison:


    private static void performanceComparison() {
        System.out.println("--- Performance Comparison ---");
        System.out.println("Testing with " + DATA_SIZE + " elements\n");
        
        // Test data
        List testData = new ArrayList<>();
        for (int i = 0; i < DATA_SIZE; i++) {
            testData.add((int) (Math.random() * DATA_SIZE));
        }
        
        // ArrayList performance
        System.out.println("ArrayList Performance:");
        testArrayListPerformance(testData);
        
        // HashMap performance
        System.out.println("\nHashMap Performance:");
        testHashMapPerformance(testData);
        
        // TreeSet performance
        System.out.println("\nTreeSet Performance:");
        testTreeSetPerformance(testData);
        
        // Summary comparison
        System.out.println("\n=== Performance Summary ===");
        System.out.println("Operation    | ArrayList | HashMap | TreeSet");
        System.out.println("-------------|-----------|---------|--------");
        System.out.println("Insert       | O(1)*     | O(1)*   | O(log n)");
        System.out.println("Search       | O(n)      | O(1)*   | O(log n)");
        System.out.println("Delete       | O(n)      | O(1)*   | O(log n)");
        System.out.println("Iteration    | O(n)      | O(n)    | O(n)");
        System.out.println("Memory       | Low       | Medium  | Medium");
        System.out.println("Duplicates   | Allowed   | Values  | Not allowed");
        System.out.println("Ordering     | Insertion | None    | Natural/Custom");
        System.out.println("* Average case, worst case can be O(n)");
    }
    
    private static void testArrayListPerformance(List testData) {
        ArrayList arrayList = new ArrayList<>();
        
        // Insert performance
        long start = System.currentTimeMillis();
        for (Integer value : testData) {
            arrayList.add(value);
        }
        long insertTime = System.currentTimeMillis() - start;
        
        // Search performance
        start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            arrayList.contains(testData.get(i));
        }
        long searchTime = System.currentTimeMillis() - start;
        
        // Random access performance
        start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            arrayList.get(i % arrayList.size());
        }
        long accessTime = System.currentTimeMillis() - start;
        
        System.out.printf("  Insert: %d ms, Search: %d ms, Access: %d ms%n", 
                         insertTime, searchTime, accessTime);
    }
    
    private static void testHashMapPerformance(List testData) {
        HashMap hashMap = new HashMap<>();
        
        // Insert performance
        long start = System.currentTimeMillis();
        for (int i = 0; i < testData.size(); i++) {
            hashMap.put(testData.get(i), i);
        }
        long insertTime = System.currentTimeMillis() - start;
        
        // Search performance
        start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            hashMap.containsKey(testData.get(i));
        }
        long searchTime = System.currentTimeMillis() - start;
        
        System.out.printf("  Insert: %d ms, Search: %d ms%n", insertTime, searchTime);
    }
    
    private static void testTreeSetPerformance(List testData) {
        TreeSet treeSet = new TreeSet<>();
        
        // Insert performance
        long start = System.currentTimeMillis();
        for (Integer value : testData) {
            treeSet.add(value);
        }
        long insertTime = System.currentTimeMillis() - start;
        
        // Search performance
        start = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            treeSet.contains(testData.get(i));
        }
        long searchTime = System.currentTimeMillis() - start;
        
        System.out.printf("  Insert: %d ms, Search: %d ms, Size: %d (unique)%n", 
                         insertTime, searchTime, treeSet.size());
    }
}
                
Solution Features:
  • Comprehensive demonstrations of ArrayList, HashMap, and TreeSet
  • All major operations: add, remove, search, iterate
  • Performance benchmarking and comparison
  • Real-world examples with practical use cases
  • Detailed performance characteristics analysis

🧪 Hands-on Lab Exercise

Lab 17: Student Management System

Task: Create a comprehensive student management system using various collection types to store and manipulate student data efficiently.

Requirements:

  • Use ArrayList<Student> to maintain student records
  • Use HashMap<String, Student> for quick student lookup by ID
  • Use TreeSet<Student> to maintain students sorted by GPA
  • Implement search, sort, and filter operations
  • Create custom comparators for different sorting criteria
  • Demonstrate iterator usage for safe collection modification
Challenge: Implement a course enrollment system using nested collections (Map<String, Set<Student>>) and ensure data consistency across all collections.

📚 Lecture Summary

Key Collections Covered

  • List: ArrayList, LinkedList, Vector
  • Set: HashSet, TreeSet, LinkedHashSet
  • Map: HashMap, TreeMap, LinkedHashMap
  • Queue: LinkedList, PriorityQueue

Important Concepts

  • Collection interfaces and implementations
  • Iterator patterns and safe iteration
  • Comparable vs Comparator
  • Performance characteristics

Best Practices

  • Choose appropriate collection based on use case
  • Use generics for type safety
  • Prefer interface types for variable declarations
  • Use enhanced for loops when possible
  • Handle ConcurrentModificationException
  • Consider performance implications

🎯 Next Lecture Preview

Lecture 18: Generics and Type Safety

  • Generic classes and methods
  • Bounded type parameters
  • Wildcards and type erasure
  • Generic collections and type safety