- 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);
}
}
}
- 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());
}
}
}
- 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:
-
Every node is either red or black
-
Root is always black
-
Red nodes cannot have red children
-
Every path from root to leaves contains same number of black nodes
-
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.