Java TreeSet Tutorial with Examples

TreeSet is part of the Java Collections Framework and provides an implementation of the NavigableSet interface. It is a sorted set backed by a TreeMap, which means it maintains its elements in ascending order. This tutorial covers all methods of TreeSet with examples and outputs, highlighting key points, use cases, best practices, performance considerations, and a real-time example with CRUD operations.

Table of Contents

  1. Introduction
  2. Key Points
  3. TreeSet Methods
    • add()
    • addAll()
    • remove()
    • clear()
    • size()
    • isEmpty()
    • contains()
    • iterator()
    • descendingIterator()
    • first()
    • last()
    • pollFirst()
    • pollLast()
    • ceiling()
    • floor()
    • higher()
    • lower()
    • subSet()
    • headSet()
    • tailSet()
  4. Use Cases
  5. Best Practices
  6. Performance Considerations
  7. Real-time Example with CRUD Operations
  8. Conclusion

1. Introduction

A TreeSet in Java is a part of the Java Collections Framework and provides a way to store unique elements in a sorted manner. It is found in the java.util package and is backed by a TreeMap, ensuring that elements are stored in ascending order.

2. Key Points

  • TreeSet does not allow duplicate elements.
  • It maintains elements in ascending order.
  • It allows null values until Java 1.6 (null values are not allowed in later versions).
  • It is not synchronized.
  • It provides logarithmic time performance for basic operations like add, remove, and contains.

3. TreeSet Methods

3.1. add()

The add() method is used to insert elements into the TreeSet.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        System.out.println(fruits);
    }
}

Output:

[Apple, Banana, Mango]

3.2. addAll()

The addAll() method adds all elements of a collection to the TreeSet.

Example:

import java.util.TreeSet;
import java.util.Arrays;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.addAll(Arrays.asList("Banana", "Mango"));
        System.out.println(fruits);
    }
}

Output:

[Apple, Banana, Mango]

3.3. remove()

The remove() method removes the specified element from the TreeSet.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        fruits.remove("Banana");
        System.out.println(fruits); // [Apple, Mango]
    }
}

Output:

[Apple, Mango]

3.4. clear()

The clear() method removes all elements from the TreeSet.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        fruits.clear();
        System.out.println(fruits); // []
    }
}

Output:

[]

3.5. size()

The size() method returns the number of elements in the TreeSet.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        System.out.println(fruits.size()); // 3
    }
}

Output:

3

3.6. isEmpty()

The isEmpty() method checks if the TreeSet is empty.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        System.out.println(fruits.isEmpty()); // true
        fruits.add("Apple");
        System.out.println(fruits.isEmpty()); // false
    }
}

Output:

true
false

3.7. contains()

The contains() method checks if the TreeSet contains a specified element.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        System.out.println(fruits.contains("Banana")); // true
        System.out.println(fruits.contains("Mango")); // false
    }
}

Output:

true
false

3.8. iterator()

The iterator() method returns an iterator for the elements in the TreeSet.

Example:

import java.util.TreeSet;
import java.util.Iterator;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        Iterator<String> iterator = fruits.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

Output:

Apple
Banana
Mango

3.9. descendingIterator()

The descendingIterator() method returns an iterator for the elements in reverse order.

Example:

import java.util.TreeSet;
import java.util.Iterator;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        Iterator<String> iterator = fruits.descendingIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

Output:

Mango
Banana
Apple

3.10. first()

The first() method returns the first (lowest) element in the TreeSet.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        System.out.println(fruits.first()); // Apple
    }
}

Output:

Apple

3.11. last()

The last() method returns the last (highest) element in the TreeSet.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        System.out.println(fruits.last()); // Mango
    }
}

Output:

Mango

3.12. pollFirst()

The pollFirst() method removes and returns the first (lowest) element in the TreeSet.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        System.out.println(fruits.pollFirst()); // Apple
        System.out.println(fruits); // [Banana, Mango]
    }
}

Output:

Apple
[Banana, Mango]

3.13. pollLast()

The pollLast() method removes and returns the last (highest) element in the TreeSet.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> fruits = new TreeSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");
        System.out.println(fruits.pollLast()); // Mango
        System.out.println(fruits); // [Apple, Banana]
    }
}

Output:

Mango
[Apple, Banana]

3.14. ceiling()

The ceiling() method returns the least element in this set greater than or equal to the given element, or null if there is no such element.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<Integer> numbers = new TreeSet<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        System



.out.println(numbers.ceiling(25)); // 30
    }
}

Output:

30

3.15. floor()

The floor() method returns the greatest element in this set less than or equal to the given element, or null if there is no such element.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<Integer> numbers = new TreeSet<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        System.out.println(numbers.floor(25)); // 20
    }
}

Output:

20

3.16. higher()

The higher() method returns the least element in this set strictly greater than the given element, or null if there is no such element.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<Integer> numbers = new TreeSet<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        System.out.println(numbers.higher(20)); // 30
    }
}

Output:

30

3.17. lower()

The lower() method returns the greatest element in this set strictly less than the given element, or null if there is no such element.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<Integer> numbers = new TreeSet<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        System.out.println(numbers.lower(20)); // 10
    }
}

Output:

10

3.18. subSet()

The subSet() method returns a view of the portion of this set whose elements range from fromElement, inclusive, to toElement, exclusive.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<Integer> numbers = new TreeSet<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(40);
        numbers.add(50);
        System.out.println(numbers.subSet(20, 40)); // [20, 30]
    }
}

Output:

[20, 30]

3.19. headSet()

The headSet() method returns a view of the portion of this set whose elements are strictly less than toElement.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<Integer> numbers = new TreeSet<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(40);
        numbers.add(50);
        System.out.println(numbers.headSet(30)); // [10, 20]
    }
}

Output:

[10, 20]

3.20. tailSet()

The tailSet() method returns a view of the portion of this set whose elements are greater than or equal to fromElement.

Example:

import java.util.TreeSet;

public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<Integer> numbers = new TreeSet<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(40);
        numbers.add(50);
        System.out.println(numbers.tailSet(30)); // [30, 40, 50]
    }
}

Output:

[30, 40, 50]

4. Use Cases

  • Sorted collections: TreeSet is used when you need a collection of unique elements sorted in natural order.
  • Range views: It can be used to create subsets of data that fall within a specified range.
  • Navigable operations: It is useful for applications requiring navigation methods like finding the ceiling, floor, higher, and lower elements.

5. Best Practices

  • Use appropriate comparator: If natural ordering is not suitable, use a custom comparator to define the order of elements.
  • Avoid frequent traversals: Iterating over a TreeSet is slower than iterating over a HashSet due to its tree structure.
  • Use HashSet if order is not important: If sorting is not required, consider using HashSet for better performance.

6. Performance Considerations

  • Logarithmic time performance: TreeSet provides logarithmic time performance for basic operations like add, remove, and contains.
  • Memory usage: Each element in a TreeSet requires additional memory for storing tree structure.
  • Thread safety: TreeSet is not synchronized. Use Collections.synchronizedSet() if thread safety is needed.

7. Real-time Example with CRUD Operations

Managing an Employee Set:

Employee.java:

public class Employee implements Comparable<Employee> {
    private String name;
    private int id;

    public Employee(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public int getId() {
        return id;
    }

    @Override
    public String toString() {
        return "Employee{name='" + name + "', id=" + id + "}";
    }

    @Override
    public int compareTo(Employee other) {
        return Integer.compare(this.id, other.id);
    }

    @Override
    public int hashCode() {
        return Integer.hashCode(id);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Employee employee = (Employee) obj;
        return id == employee.id;
    }
}

Main.java:

import java.util.TreeSet;

public class Main {
    public static void main(String[] args) {
        TreeSet<Employee> employeeSet = new TreeSet<>();

        // Create
        employeeSet.add(new Employee("Aarav", 102));
        employeeSet.add(new Employee("Vivaan", 104));
        employeeSet.add(new Employee("Diya", 103));

        // Read
        for (Employee employee : employeeSet) {
            System.out.println(employee);
        }

        // Update
        employeeSet.remove(new Employee("Vivaan", 104));
        employeeSet.add(new Employee("Vivaan", 105));
        System.out.println("After Update:");
        for (Employee employee : employeeSet) {
            System.out.println(employee);
        }

        // Delete
        employeeSet.remove(new Employee("Aarav", 102));
        System.out.println("After Deletion:");
        for (Employee employee : employeeSet) {
            System.out.println(employee);
        }
    }
}

Output:

Employee{name='Aarav', id=102}
Employee{name='Diya', id=103}
Employee{name='Vivaan', id=104}
After Update:
Employee{name='Diya', id=103}
Employee{name='Vivaan', id=105}
After Deletion:
Employee{name='Diya', id=103}
Employee{name='Vivaan', id=105}

8. Conclusion

The TreeSet class in Java is a powerful class for managing unique collections of elements in a sorted order. By understanding its methods, use cases, and best practices, you can effectively utilize TreeSet in your Java applications. This tutorial covers the essential methods with examples and demonstrates a real-time example with CRUD operations.

Comments