Understanding Java Set Collections and Data Structures

  1. Set Collection Fundamentals

1.1 Set Collection Characteristics

Set collections in Java provide unique storage capabilities:

  • No duplicate elements allowed
  • No indexed access, preventing traditional for-loop iteration

1.2 Basic Set Implementation

Example demonstrating string storage and iteration:

public class SetBasicsDemo {
    public static void main(String[] args) {
        // Initialize collection
        Set<String> uniqueStrings = new TreeSet<>();
        
        // Insert elements
        uniqueStrings.add("gamma");
        uniqueStrings.add("alpha");
        uniqueStrings.add("alpha"); // Duplicate will be ignored
        uniqueStrings.add("beta");

        // Iterator traversal
        Iterator<String> setIterator = uniqueStrings.iterator();
        while (setIterator.hasNext()) {
            String current = setIterator.next();
            System.out.println(current);
        }
        
        // Enhanced for-loop traversal
        for (String current : uniqueStrings) {
            System.out.println(current);
        }
    }
}
  1. TreeSet Collection Deep Dive

2.1 TreeSet Features

TreeSet offers sorted storage with these properties:

  • Automatic duplicate prevention
  • No indexed access
  • Element sorting based on defined rules:
    • Natural ordering via TreeSet()
    • Custom comparator via TreeSet(Comparator)

2.2 TreeSet with Integer Elements

public class IntegerTreeSetDemo {
    public static void main(String[] args) {
        TreeSet<Integer> numberSet = new TreeSet<>();
        
        numberSet.add(25);
        numberSet.add(15);
        numberSet.add(35);
        numberSet.add(5);
        numberSet.add(45);
        numberSet.add(15); // Duplicate ignored
        
        // Display sorted elements
        for (Integer number : numberSet) {
            System.out.println(number);
        }
    }
}

2.3 Natural Ordering with Comparable

Implement custom sorting by having the class implement Comparable:

public class Employee implements Comparable<Employee> {
    private String fullName;
    private int employeeAge;
    
    public Employee(String fullName, int employeeAge) {
        this.fullName = fullName;
        this.employeeAge = employeeAge;
    }
    
    @Override
    public int compareTo(Employee other) {
        // Primary sort by age
        int ageComparison = this.employeeAge - other.employeeAge;
        // Secondary sort by name if ages equal
        return ageComparison == 0 ? this.fullName.compareTo(other.fullName) : ageComparison;
    }
    
    @Override
    public String toString() {
        return "Employee{name='" + fullName + "', age=" + employeeAge + "}";
    }
}

public class EmployeeTreeSetDemo {
    public static void main(String[] args) {
        TreeSet<Employee> staff = new TreeSet<>();
        
        staff.add(new Employee("Alice Johnson", 32));
        staff.add(new Employee("Bob Smith", 28));
        staff.add(new Employee("Charlie Brown", 35));
        staff.add(new Employee("David Wilson", 32));
        
        for (Employee emp : staff) {
            System.out.println(emp);
        }
    }
}

2.4 Comparator-based Sorting

Alternative sorting using external comparator:

public class Product {
    private String productName;
    private double price;
    
    public Product(String productName, double price) {
        this.productName = productName;
        this.price = price;
    }
    
    // Getters...
}

public class ProductSortingDemo {
    public static void main(String[] args) {
        TreeSet<Product> inventory = new TreeSet<>(new Comparator<Product>() {
            @Override
            public int compare(Product p1, Product p2) {
                // Sort by price ascending
                int priceComparison = Double.compare(p1.getPrice(), p2.getPrice());
                // If prices equal, sort by name
                return priceComparison == 0 ? p1.getProductName().compareTo(p2.getProductName()) : priceComparison;
            }
        });
        
        inventory.add(new Product("Laptop", 999.99));
        inventory.add(new Product("Mouse", 29.99));
        inventory.add(new Product("Keyboard", 79.99));
        inventory.add(new Product("Monitor", 299.99));
        
        for (Product item : inventory) {
            System.out.println(item.getProductName() + ": $" + item.getPrice());
        }
    }
}
  1. Data Structures Behind TreeSet

3.1 Binary Tree Basics

A binary tree is a hierarchical structure where each node has at most two children (left and right). The degree of a node refers to its number of direct children.

3.2 Binary Search Tree (BST)

BST properties:

  • Maximum of two child nodes per parent
  • Left subtree contains only values less than parent
  • Right subtree contains only values greater than parent

3.3 Balanced Binary Tree

Maintains height balance where the height difference between left and right subtreees of any node is at most 1. Rotations (left or right) are performed when insertion creates imbalance.

3.4 Red-Black Tree

A self-balancing binary search tree with these rules:

  1. Every node is either red or black

  2. Root is always black

  3. Red nodes cannot have red children

  4. Every path from root to leaves contains same number of black nodes

  5. HashSet Collection


4.1 HashSet Characteristics

  • Hash table-based implementation
  • Unordered storage
  • No duplicate elements
  • No endexed access

4.2 HashSet Basic Usage

public class HashSetExample {
    public static void main(String[] args) {
        HashSet<String> wordCollection = new HashSet<>();
        
        wordCollection.add("Java");
        wordCollection.add("Python");
        wordCollection.add("C++");
        wordCollection.add("Java"); // Duplicate ignored
        
        for (String word : wordCollection) {
            System.out.println(word);
        }
    }
}

4.3 Hash Code Understanding

Hash code is an integer value computed from object properties. Object.hashCode() returns this value. Rules:

  • Same object always returns same hash code
  • Equal objects must have equal hash codes

4.4 Hash Table Structure

JDK 8 optimization:

  • ≤8 elements: Array + linked list
  • >8 elements: Array + red-black tree for better performance

4.5 HashSet with Custom Objects

public class User {
    private String username;
    private int userId;
    
    public User(String username, int userId) {
        this.username = username;
        this.userId = userId;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        
        User other = (User) obj;
        return userId == other.userId && Objects.equals(username, other.username);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(username, userId);
    }
}

public class UserSetDemo {
    public static void main(String[] args) {
        HashSet<User> userDirectory = new HashSet<>();
        
        userDirectory.add(new User("john_doe", 1001));
        userDirectory.add(new User("jane_smith", 1002));
        userDirectory.add(new User("bob_wilson", 1003));
        userDirectory.add(new User("bob_wilson", 1003)); // Duplicate ignored
        
        for (User user : userDirectory) {
            System.out.println(user.getUsername() + " - ID: " + user.getUserId());
        }
    }
}

Key Principal: For HashSet to correctly handle custom objects, both equals() and hashCode() must be properly overridden.

Tags: java Set TreeSet HashSet DataStructures

Posted on Sun, 10 May 2026 14:20:55 +0000 by The Swedish Tower