TreeSet

TreeSet

In Java, a TreeSet is a part of the java.util package and implements the NavigableSet interface, which extends SortedSet. Internally, it uses a Red-Black Tree (a self-balancing binary search tree), which ensures that the elements are always stored in sorted order. A TreeSet does not allow duplicate elements and does not permit null values. It is commonly used when you need to maintain a sorted collection, and it provides log-time complexity for basic operations like adding, removing, and searching elements.

Advantages #

  1. Sorted Order: Elements are automatically sorted in natural order (or using a custom comparator), which is useful when maintaining sorted data is required.
  2. Efficient Range Queries: The TreeSet supports efficient methods for obtaining subsets, headsets, and tailsets, allowing for quick range-based operations.
  3. Navigable: Offers convenient methods like first(), last(), lower(), and higher() for accessing elements based on their values.
  4. No Duplicates: Ensures that the set contains only unique elements.
  5. Consistent Performance: Since it is based on a balanced tree, performance remains consistent, even with large data sets.

Disadvantages #

  1. Slower than HashSet: Operations like add, remove, and search have a time complexity of O(log n), which is slower than HashSet, which operates in O(1) on average.
  2. No Null Elements: Does not permit null values, and attempting to add a null element results in a NullPointerException.
  3. Higher Memory Overhead: Requires more memory compared to a HashSet due to the additional structure ( parent/child pointers and color information) of the red-black tree.
  4. Complexity in Maintaining Order: Maintaining sorted order adds complexity and overhead, making it slower for operations that don’t require ordering.

Time and Space Complexity #

OperationTime ComplexitySpace Complexity
Add (add)O(log n)O(n)
Remove (remove)O(log n)O(n)
Contains (contains)O(log n)O(n)
First (first)O(log n)O(n)
Last (last)O(log n)O(n)
HeadSet (headSet)O(log n)O(n)
TailSet (tailSet)O(log n)O(n)
SubSet (subSet)O(log n)O(n)

Examples #

  1. Add Operation

    • Time Complexity: O(log n)
    TreeSet<Integer> treeSet = new TreeSet<>();
    treeSet.add(10); // [10]
    treeSet.add(5);  // [5, 10]
    treeSet.add(15); // [5, 15, 10]
    treeSet.add(20); // [5, 15, 10, 20]
    
  2. Remove Operation

    • Time Complexity: O(log n)
    treeSet.remove(20); // [5, 15, 10]
    
  3. Contains Operation

    • Time Complexity: O(log n)
    treeSet.contains(5); // true
    
  4. First Operation

    • Time Complexity: O(log n)
    treeSet.first(); // 5
    
  5. Last Operation

    • Time Complexity: O(log n)
    treeSet.last(); // 15
    
  6. HeadSet Operation

    • Time Complexity: O(log n)
    treeSet.headSet(10); // [5]
    
  7. TailSet Operation

    • Time Complexity: O(log n)
    treeSet.tailSet(10);  // [10, 15]
    
  8. SubSet Operation

    • Time Complexity: O(log n)
    treeSet.subSet(5, 15);  // [5, 10]