\| Aspect \| HashSet \| TreeSet \|
\|-------------------------\|------------------------------------------------\|----------------------------------------------\|
\| Underlying Data Structure \| HashMap (internally stores elements using a hash table) \| Red-Black Tree (self-balancing binary search tree) \|
\| Ordering \| No ordering is guaranteed. The elements are stored in an unordered manner and their order may change over time. \| Sorted in natural order (ascending order by default) or by a custom comparator if provided. \|
\| Performance (Time Complexity) \| Faster for basic operations (like add, remove, contains) since operations are performed in constant time, O(1) on average. \| Slower for basic operations because operations are performed in O(log n) time due to tree traversal. \|
\| Duplicates \| Does not allow duplicates (same as TreeSet). \| Does not allow duplicates (same as HashSet). \|
\| Null Elements \| Allows one null element. \| Does not allow null elements (will throw NullPointerException
). \|
\| Ordering Control \| No control over element order, as it's based on hash codes. \| Can control order via natural ordering (e.g., integers are ordered from smallest to largest) or by providing a custom comparator. \|
\| Use Case \| Use when you need a fast lookup without caring about the order of elements. \| Use when you need a sorted set and care about element order. \|
\| Iterating Elements \| Iteration order is unpredictable. \| Iteration order is sorted according to natural order or custom comparator. \|
\| Performance for Insertions/Deletions \| O(1) on average, but depends on the hash function. Worst case is O(n) if too many collisions occur. \| O(log n) for insertions and deletions due to the red-black tree balancing. \|
\| Interface Implemented \| Implements Set interface. \| Implements Set and NavigableSet interfaces, which provide methods for sorted sets like headSet()
, tailSet()
. \|
When to Use:
- HashSet: Use when you need fast performance (O(1) average time complexity) for adding, removing, and checking for the existence of elements, and you don't care about the order of elements.
- TreeSet: Use when you need the elements to be sorted in a specific order, or if you need additional operations like finding subsets (
headSet()
,tailSet()
), but are okay with slightly slower performance (O(log n)).
Examples:
HashSet Example:
import java.util.HashSet; public class HashSetExample {
public static void main(String args) {
HashSet<Integer> hashSet = new HashSet<>();
hashSet.add(3);
hashSet.add(1);
hashSet.add(2);
System.out.println(hashSet); // Output might be in any order, e.g., [1, 2, 3]
}
}
TreeSet Example:
import java.util.TreeSet; public class TreeSetExample {
public static void main(String args) {
TreeSet<Integer> treeSet = new TreeSet<>();
treeSet.add(3);
treeSet.add(1);
treeSet.add(2);
System.out.println(treeSet); // Output: [1, 2, 3] (sorted order)
}
}
Summary:
- HashSet is best when you prioritize performance over order and need constant time for basic operations.
- TreeSet is best when you need elements to be sorted and don't mind paying a performance cost with logarithmic time for operations.