Java Collections Framework: Theory and Practice

Part 1: Theoretical Knowledge

The eleventh week of study focused on Java's Collections Framework, building upon the generic programming concepts covered in the previous week. The theoretical foundation centered on understanding various collection classes, their interfaces, and implementation strategies in Java.

The Java Collections Framework provides a unified architecture for storing and manipulating groups of objects. It includes interfaces, implementations, and algorithms that facilitate common operations on collections of data.

Part 2: Laboratory Exercises

1. Objectives and Requirements

  • Master the usage and common APIs of Vector, Stack, and Hashtable classes
  • Understand the composition of the Java Collections Framework
  • Learn the purpose and common APIs of ArrayList and LinkedList classes
  • Explore the usage of HashSet and TreeSet classes
  • Understand the purpose and common APIs of HashMap and TreeMap classes
  • Experience pair programming to understand collaborative development

2. Experiment Content and Procedures

Experiment 1: Core Collection Classes

Test Program 1: Legacy Collection Classes

The following program demonstrates the usage of Vector, Stack, and Hashtable classes:


import java.util.Vector;

class Animal {
    private int id;
    
    Animal(int i) {
        id = i;
    }
    
    void display() {
        System.out.println("Animal #" + id);
    }
}

class Cat extends Animal {
    Cat(int i) {
        super(i);
    }
    
    void display() {
        System.out.println("Cat #" + id);
    }
}

class Dog extends Animal {
    Dog(int i) {
        super(i);
    }
    
    void display() {
        System.out.println("Dog #" + id);
    }
}

public class AnimalCollection {
    public static void main(String[] args) {
        Vector<animal> animals = new Vector<>();
        for (int i = 0; i < 7; i++)
            animals.addElement(new Cat(i));
        animals.addElement(new Dog(7));
        
        for (int i = 0; i < animals.size(); i++) {
            if (animals.elementAt(i) instanceof Cat) {
                ((Cat) animals.elementAt(i)).display();
            } else {
                ((Dog) animals.elementAt(i)).display();
            }
        }
    }
}
</animal>

Test Program 2: Stack Implementation


import java.util.*;

public class StackDemo {
    static String[] quarters = { "Q1", "Q2", "Q3", "Q4" };
    
    public static void main(String[] args) {
        Stack<string> stk = new Stack<>();
        for (int i = 0; i < quarters.length; i++)
            stk.push(quarters[i]);
        System.out.println(stk);
        System.out.println("Element at position 2=" + stk.elementAt(2));
        while (!stk.empty())
            System.out.println(stk.pop());
    }
}
</string>

Test Program 3: Hashtable Usage


import java.util.*;

class Counter {
    int count = 1;
    
    public String toString() {
        return Integer.toString(count);
    }
}

public class FrequencyAnalysis {
    public static void main(String[] args) {
        Hashtable<integer counter=""> frequencyMap = new Hashtable<>();
        for (int i = 0; i < 10000; i++) {
            Integer randomValue = (int) (Math.random() * 20);
            if (frequencyMap.containsKey(randomValue))
                frequencyMap.get(randomValue).count++;
            else
                frequencyMap.put(randomValue, new Counter());
        }
        System.out.println(frequencyMap);
    }
}
</integer>

Test Program 4: List Implementations

ArrayList Demonstration


import java.util.*;

public class ArrayListExample {
    public static void main(String[] args) {
        ArrayList<object> al = new ArrayList<>();
        // Add various elements to the ArrayList
        al.add(11);
        al.add(12);
        al.add(13);
        al.add("Hello");
        
        // Print elements using index-based access
        System.out.println("Retrieving by index:");
        for (int i = 0; i < al.size(); i++) {
            System.out.println("Element " + i + " = " + al.get(i));
        }
    }
}
</object>

LinkedList Demonstration


import java.util.*;

public class LinkedListExample {
    public static void main(String[] args) {
        LinkedList<object> list = new LinkedList<>();
        list.add(new Object());
        list.add("Hello");
        list.add("World");
        
        ListIterator<object> iterator = list.listIterator(0);
        while (iterator.hasNext())
            System.out.println(iterator.next());
            
        if (list.indexOf("Hello") < 0)   
            System.err.println("Lookup does not work");
        else
            System.err.println("Lookup works");
    }
}
</object></object>

Test Program 5: Advanced List Operations

The following program demonstrates advanced operations on linked lists:


import java.util.*;

public class AdvancedLinkedListOperations {
    public static void main(String[] args) {
        List<string> listA = new LinkedList<>();
        listA.add("Amy");
        listA.add("Carl");
        listA.add("Erica");

        List<string> listB = new LinkedList<>();
        listB.add("Bob");
        listB.add("Doug");
        listB.add("Frances");
        listB.add("Gloria");

        // Merge elements from B into A
        ListIterator<string> aIterator = listA.listIterator();
        Iterator<string> bIterator = listB.iterator();

        while (bIterator.hasNext()) {
            if (aIterator.hasNext()) aIterator.next();
            aIterator.add(bIterator.next());
        }

        System.out.println("Merged list: " + listA);

        // Remove every second element from B
        bIterator = listB.iterator();
        while (bIterator.hasNext()) {
            bIterator.next(); // Skip one element
            if (bIterator.hasNext()) {
                bIterator.next(); // Skip next element
                bIterator.remove(); // Remove the element
            }
        }

        System.out.println("Modified list B: " + listB);

        // Bulk operation: remove all elements in B from A
        listA.removeAll(listB);

        System.out.println("Final list A: " + listA);
    }
}
</string></string></string></string>

Test Program 6: Set Implementations

HashSet Demonstration


import java.util.*;

public class HashSetExample {
    public static void main(String[] args) {
        Set<string> h = new HashSet<>();
        h.add("One");
        h.add("Two");
        h.add("One"); // DUPLICATE
        h.add("Three");
        
        Iterator<string> it = h.iterator();
        while (it.hasNext()) {
             System.out.println(it.next());
        }
    }
}
</string></string>

Unique Word Counter


import java.util.*;

public class UniqueWordCounter {
    public static void main(String[] args) {
        Set<string> words = new HashSet<>();
        long totalTime = 0;

        try (Scanner in = new Scanner(System.in)) {
            while (in.hasNext()) {
                String word = in.next();
                long callTime = System.currentTimeMillis();
                words.add(word);
                callTime = System.currentTimeMillis() - callTime;
                totalTime += callTime;
            }
        }

        Iterator<string> iter = words.iterator();
        for (int i = 1; i <= 20 && iter.hasNext(); i++)
            System.out.println(iter.next());
        System.out.println(". . .");
        System.out.println(words.size() + " distinct words. " + totalTime + " milliseconds.");
    }
}
</string></string>

Test Program 7: TreeSet Implementation

Comparable Item Class


import java.util.*;

public class Item implements Comparable<item> {
    private String description;
    private int partNumber;

    public Item(String description, int partNumber) {
       this.description = description;
       this.partNumber = partNumber;
    }

    public String getDescription() {
       return description;
    }

    public String toString() {
       return "[description=" + description + ", partNumber=" + partNumber + "]";
    }

    public boolean equals(Object otherObject) {
       if (this == otherObject) return true;
       if (otherObject == null) return false;
       if (getClass() != otherObject.getClass()) return false;
       Item other = (Item) otherObject;
       return Objects.equals(description, other.description) && partNumber == other.partNumber;
    }

    public int hashCode() {
       return Objects.hash(description, partNumber);
    }

    public int compareTo(Item other) {
       int diff = Integer.compare(partNumber, other.partNumber);
       return diff != 0 ? diff : description.compareTo(other.description);
    }
}
</item>

TreeSet Sorting Example


import java.util.*;

public class TreeSetSortingExample {
    public static void main(String[] args) {
        SortedSet<item> parts = new TreeSet<>();
        parts.add(new Item("Toaster", 1234));
        parts.add(new Item("Widget", 4562));
        parts.add(new Item("Modem", 9912));
        System.out.println("Sorted by part number: " + parts);

        NavigableSet<item> sortByDescription = new TreeSet<>(
              Comparator.comparing(Item::getDescription));

        sortByDescription.addAll(parts);
        System.out.println("Sorted by description: " + sortByDescription);
    }
}
</item></item>

Test Program 8: Map Implementations

HashMap Demonstration


import java.util.*;

public class HashMapExample {
   public static void main(String[] args) {
      Map<string string=""> companyLocations = new HashMap<>();
      // Map company names to addresses
      companyLocations.put("Adobe", "Mountain View, CA");
      companyLocations.put("IBM", "White Plains, NY");
      companyLocations.put("Sun", "Mountain View, CA");
      
      String query = "Adobe";
      String result = companyLocations.get(query);
      System.out.println("Adobe is located in: " +  result);
  }
}
</string>

Employee Class


/**
 * A minimal employee class for testing purposes.
 */
public class Employee
{
   private String name;
   private double salary;

   /**
    * Constructs an employee with default salary.
    * @param name the employee name
    */
   public Employee(String name)
   {
      this.name = name;
      salary = 0;
   }

   public String toString()
   {
      return "[name=" + name + ", salary=" + salary + "]";
   }
}

Map Operations Example


import java.util.*;

public class MapOperationsExample {
    public static void main(String[] args) {
       Map<string employee=""> staff = new HashMap<>();
       staff.put("144-25-5464", new Employee("Amy Lee"));
       staff.put("567-24-2546", new Employee("Harry Hacker"));
       staff.put("157-62-7935", new Employee("Gary Cooper"));
       staff.put("456-62-5527", new Employee("Francesca Cruz"));

       // Print all entries
       System.out.println("Employee database: " + staff);

       // Remove an entry
       staff.remove("567-24-2546");

       // Replace an entry
       staff.put("456-62-5527", new Employee("Francesca Miller"));

       // Look up a value
       System.out.println("Employee lookup: " + staff.get("157-62-7935"));

       // Iterate through all entries
       staff.forEach((id, employee) -> 
          System.out.println("ID=" + id + ", Employee=" + employee));
    }
}
</string>

3. Pair Programming Exercise

Pair programming is a collaborative development approach where two programmers work to gether at one workstation. One programmer (the driver) writes code, while the other (the observer/navigator) reviews each line of code as it's written and thinks strategically about the direction of the work.

Benefits of Pair Programming:

  • Improved code quality through real-time review Enhanced knowledge sharing between team members - Reduced defects and better problem-solving
  • Increased code maintainability

Exercise 1: ID Information System

The following program implements an ID information system with various search and filter operations:


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class IDInformationSystem {
    
    private static ArrayList<person> personList;
    
    public static Person findPersonByName(String name) {
        Person foundPerson = null;
        for (Person person : personList) {
            if(person.getName().equals(name)) {
                foundPerson = person;
                break;
            }
        }
        return foundPerson;
    }
    
    public static Person findPersonById(String id) {
        Person foundPerson = null;
        for (Person person : personList) {
            if(person.getId().equals(id)) {
                foundPerson = person;
                break;
            }
        }
        return foundPerson;
    }
      
    private static ArrayList<person> findPeopleWithClosestAge(int targetAge) {
        int minDifference = Integer.MAX_VALUE;
        int closestIndex = 0;
        ArrayList<person> closestPeople = new ArrayList<>();
        
        // Find the person(s) with age closest to targetAge
        for (int i = 0; i < personList.size(); i++) {
            int difference = Math.abs(personList.get(i).getAge() - targetAge);
            if (difference < minDifference) {
                minDifference = difference;
                closestIndex = i;
            }
        }
        
        // Collect all people with the closest age
        for(Person person : personList) {
            if(Math.abs(person.getAge() - personList.get(closestIndex).getAge()) == 0) {
                closestPeople.add(person);
            }
        }
        return closestPeople;
    }

    public static void main(String[] args) {
        personList = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        File file = new File("id_data.txt");
        
        try {
            FileInputStream fileStream = new FileInputStream(file);
            BufferedReader reader = new BufferedReader(new InputStreamReader(fileStream));
            String line = null;
            
            while ((line = reader.readLine()) != null) {
                String[] information = line.split("\\s+");
                Person person = new Person();
                person.setName(information[0]);
                person.setId(information[1]);
                int age = Integer.parseInt(information[2]);
                person.setAge(age);
                person.setGender(information[3]);
                
                // Handle multiple place fields
                for(int j = 4; j < information.length; j++) {
                    person.addPlace(information[j]);
                }
                personList.add(person);
            }
        } catch (FileNotFoundException e) {
            System.out.println("File not found");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("Error reading file");
            e.printStackTrace();
        }
        
        boolean running = true;
        while (running) {
            displayMenu();
            int choice = scanner.nextInt();
            scanner.nextLine(); // Consume newline
            
            switch (choice) {
                case 1:
                    Collections.sort(personList);
                    System.out.println("People sorted by name: " + personList);
                    break;
                case 2:
                    Person oldest = findOldestPerson();
                    System.out.println("Oldest person: " + oldest);
                    break;
                case 3:
                    Person youngest = findYoungestPerson();
                    System.out.println("Youngest person: " + youngest);
                    break;
                case 4:
                    System.out.println("Enter your age:");
                    int inputAge = scanner.nextInt();
                    ArrayList<person> closestPeople = findPeopleWithClosestAge(inputAge);
                    System.out.println("People with closest age:");
                    for(Person person : closestPeople) {
                        System.out.println(person);
                    }
                    break;
                case 5:
                    System.out.println("Enter your province:");
                    String province = scanner.next();
                    findPeopleFromProvince(province);
                    break;
                case 6:
                    running = false;
                    System.out.println("Goodbye!");
                    break;
                default:
                    System.out.println("Invalid input");
            }
        }
        scanner.close();
    }
    
    private static void displayMenu() {
        System.out.println("******************************************");
        System.out.println("   1. Display all people sorted by name");
        System.out.println("   2. Find oldest person");
        System.out.println("   3. Find youngest person");
        System.out.println("   4. Find people with closest age to yours");
        System.out.println("   5. Find people from your province");
        System.out.println("   6. Exit");
        System.out.println("******************************************");
    }
    
    private static Person findOldestPerson() {
        Person oldest = personList.get(0);
        for (Person person : personList) {
            if (person.getAge() > oldest.getAge()) {
                oldest = person;
            }
        }
        return oldest;
    }
    
    private static Person findYoungestPerson() {
        Person youngest = personList.get(0);
        for (Person person : personList) {
            if (person.getAge() < youngest.getAge()) {
                youngest = person;
            }
        }
        return youngest;
    }
    
    private static void findPeopleFromProvince(String province) {
        boolean found = false;
        for (Person person : personList) {
            if (person.getPlaces().contains(province)) {
                System.out.println("Person from " + province + ": " + person);
                found = true;
            }
        }
        if (!found) {
            System.out.println("No people found from " + province);
        }
    }
}

class Person implements Comparable<person> {
    private String name;
    private String id;
    private int age;
    private String gender;
    private ArrayList<string> places;
    
    public Person() {
        places = new ArrayList<>();
    }
    
    // Getters and setters
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    
    public String getGender() { return gender; }
    public void setGender(String gender) { this.gender = gender; }
    
    public ArrayList<string> getPlaces() { return places; }
    public void addPlace(String place) { places.add(place); }
    
    @Override
    public String toString() {
        return "Person{name='" + name + "', id='" + id + "', age=" + age + 
               ", gender='" + gender + "', places=" + places + "}";
    }
    
    @Override
    public int compareTo(Person other) {
        return this.name.compareTo(other.name);
    }
}
</string></string></person></person></person></person></person>

Exercise 2: Arithmetic Quiz Generator

The following program generates arithmetic problems and evaluates user answers:


import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Scanner;

public class ArithmeticQuizGenerator {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Calculator calculator = new Calculator();
        File outputFile = new File("quiz_results.txt");
        
        if(outputFile.exists()) {
            System.out.println("Output file already exists");
        }
        
        PrintWriter output = null;
        try {
            output = new PrintWriter(new FileOutputStream(outputFile));
        } catch (Exception e) {
            System.err.println("Error creating output file");
        }
        
        int score = 0;
        System.out.println("Quiz results will be rounded to 2 decimal places");
        
        for (int i = 1; i <= 10; i++) {
            int a = (int) Math.round(Math.random() * 100);
            int b = (int) Math.round(Math.random() * 100);
            int operation = (int) Math.round(Math.random() * 3) + 1;
            
            double userAnswer = 0;
            String operationSymbol = "";
            
            switch(operation) {
                case 1: // Division
                    operationSymbol = "/";
                    System.out.println(i + ": " + a + operationSymbol + b + " = ");
                    userAnswer = scanner.nextDouble();
                    output.println(a + operationSymbol + b + "=" + userAnswer);
                    
                    double divisionResult = calculator.divide(a, b);
                    BigDecimal formattedDivision = new BigDecimal(divisionResult);
                    formattedDivision = formattedDivision.setScale(2, BigDecimal.ROUND_HALF_UP);
                    
                    if (Math.abs(userAnswer - formattedDivision.doubleValue()) < 0.001) {
                        score += 10;
                        System.out.println("Correct!");
                    } else {
                        System.out.println("Incorrect. The correct answer is: " + formattedDivision);
                    }
                    break;
                
                case 2: // Multiplication
                    operationSymbol = "*";
                    System.out.println(i + ": " + a + operationSymbol + b + " = ");
                    userAnswer = scanner.nextDouble();
                    output.println(a + operationSymbol + b + "=" + userAnswer);
                    
                    double multiplicationResult = calculator.multiply(a, b);
                    BigDecimal formattedMultiplication = new BigDecimal(multiplicationResult);
                    formattedMultiplication = formattedMultiplication.setScale(2, BigDecimal.ROUND_HALF_UP);
                    
                    if (Math.abs(userAnswer - formattedMultiplication.doubleValue()) < 0.001) {
                        score += 10;
                        System.out.println("Correct!");
                    } else {
                        System.out.println("Incorrect. The correct answer is: " + formattedMultiplication);
                    }
                    break;
                    
                case 3: // Addition
                    operationSymbol = "+";
                    System.out.println(i + ": " + a + operationSymbol + b + " = ");
                    userAnswer = scanner.nextDouble();
                    output.println(a + operationSymbol + b + "=" + userAnswer);
                    
                    double additionResult = calculator.add(a, b);
                    BigDecimal formattedAddition = new BigDecimal(additionResult);
                    formattedAddition = formattedAddition.setScale(2, BigDecimal.ROUND_HALF_UP);
                    
                    if (Math.abs(userAnswer - formattedAddition.doubleValue()) < 0.001) {
                        score += 10;
                        System.out.println("Correct!");
                    } else {
                        System.out.println("Incorrect. The correct answer is: " + formattedAddition);
                    }
                    break;
                    
                case 4: // Subtraction
                    operationSymbol = "-";
                    System.out.println(i + ": " + a + operationSymbol + b + " = ");
                    userAnswer = scanner.nextDouble();
                    output.println(a + operationSymbol + b + "=" + userAnswer);
                    
                    double subtractionResult = calculator.subtract(a, b);
                    BigDecimal formattedSubtraction = new BigDecimal(subtractionResult);
                    formattedSubtraction = formattedSubtraction.setScale(2, BigDecimal.ROUND_HALF_UP);
                    
                    if (Math.abs(userAnswer - formattedSubtraction.doubleValue()) < 0.001) {
                        score += 10;
                        System.out.println("Correct!");
                    } else {
                        System.out.println("Incorrect. The correct answer is: " + formattedSubtraction);
                    }
                    break;
            }
        }
        
        System.out.println("Final score: " + score + "/100");
        output.println("Final score: " + score + "/100");
        output.close();
        scanner.close();
    }
}

class Calculator {
    public double add(double a, double b) {
        return a + b;
    }
    
    public double subtract(double a, double b) {
        return a - b;
    }
    
    public double multiply(double a, double b) {
        return a * b;
    }
    
    public double divide(double a, double b) {
        if (b == 0) {
            throw new ArithmeticException("Division by zero");
        }
        return a / b;
    }
}

3. Summary

During this week of study, we reviewed the concepts of generic programming from the previous week and expanded our knowledge of Java's Collections Framework. We gained practical experience with various collection classes and thier APIs through hands-on experiments.

The pair programming exercises were particularly valuable, allowing us to identify our own weaknesses while helping others improve their code. This collaborative approach not only enhanced our problem-solving skills but also significantly improved our ability to read and understand code written by others.

Tags: Java Collections Framework Data Structures Object-Oriented Programming pair programming generics

Posted on Mon, 05 Oct 2026 16:16:27 +0000 by tomkure