TreeSet
IntermediateA sorted Set backed by a TreeMap — O(log n) operations with powerful range-query methods for finding nearest elements and iterating ranges.
Overview
TreeSet implements NavigableSet using a TreeMap internally (elements are keys, a constant is the value). Like TreeMap, it keeps elements in sorted order at all times (natural order or custom Comparator). All operations are O(log n). TreeSet adds Set semantics on top of TreeMap's sorted navigation: floor(), ceiling(), lower(), higher(), subSet(), headSet(), tailSet() — all returning elements near or within a range. It is the go-to choice when you need a sorted collection of unique values.
Core Operations & Sorted Iteration
TreeSet elements must implement Comparable or a Comparator must be provided. The natural ordering determines both sort order and equality — two elements that compareTo() == 0 are considered duplicates even if equals() says otherwise. This is the most common TreeSet pitfall.
Iteration always returns elements in ascending sorted order. first() and last() return boundary elements in O(log n).
import java.util.*;
public class TreeSetBasics {
public static void main(String[] args) {
// Natural order (Integer Comparable)
TreeSet<Integer> numbers = new TreeSet<>(Set.of(5, 2, 8, 1, 9, 3, 5));
System.out.println(numbers); // [1, 2, 3, 5, 8, 9] — sorted, no duplicate 5
System.out.println(numbers.first()); // 1
System.out.println(numbers.last()); // 9
System.out.println(numbers.size()); // 6
// Sorted String set
TreeSet<String> words = new TreeSet<>(
List.of("banana", "apple", "cherry", "avocado"));
System.out.println(words); // [apple, avocado, banana, cherry]
// Custom Comparator — sort by string length, then alphabetically
TreeSet<String> byLength = new TreeSet<>(
Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()));
byLength.addAll(words);
System.out.println(byLength); // [apple, banana, avocado, cherry]
// PITFALL: compareTo == 0 means duplicate, even if equals() differs
TreeSet<String> caseInsensitive = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
caseInsensitive.add("Apple");
caseInsensitive.add("apple"); // treated as duplicate — compareTo returns 0
System.out.println(caseInsensitive.size()); // 1, not 2!
}
}NavigableSet — Range Queries
floor(e) — greatest element ≤ e ceiling(e) — smallest element ≥ e lower(e) — greatest element strictly < e higher(e) — smallest element strictly > e subSet(from, fromInclusive, to, toInclusive) — range view headSet(to, inclusive) — elements below to tailSet(from, inclusive) — elements from and above pollFirst() / pollLast() — remove and return boundary descendingSet() — reversed NavigableSet view
import java.util.*;
public class TreeSetNavigation {
public static void main(String[] args) {
TreeSet<Integer> set = new TreeSet<>(Set.of(10, 20, 30, 40, 50));
// Nearest-element lookups — O(log n)
System.out.println(set.floor(25)); // 20
System.out.println(set.ceiling(25)); // 30
System.out.println(set.lower(30)); // 20 — strictly less
System.out.println(set.higher(30)); // 40 — strictly greater
// Range subsets (live views backed by original)
NavigableSet<Integer> mid = set.subSet(20, true, 40, true);
System.out.println(mid); // [20, 30, 40]
mid.add(35); // modifies original set
System.out.println(set); // [10, 20, 30, 35, 40, 50]
// headSet — elements strictly below 30
System.out.println(set.headSet(30)); // [10, 20]
System.out.println(set.headSet(30, true)); // [10, 20, 30]
// tailSet — elements from 35 upwards
System.out.println(set.tailSet(35)); // [35, 40, 50]
// Poll removes boundary elements
System.out.println(set.pollFirst()); // 10
System.out.println(set.pollLast()); // 50
System.out.println(set); // [20, 30, 35, 40]
// Descending view
System.out.println(set.descendingSet()); // [40, 35, 30, 20]
// Practical: find all scores in a grade range
TreeSet<Integer> scores = new TreeSet<>(
Set.of(45, 62, 78, 83, 91, 95, 55, 70));
System.out.println("B grades (80–89): " + scores.subSet(80, true, 90, false));
// B grades (80–89): [83]
}
}TreeSet vs HashSet — Decision Guide
HashSet — O(1) average; unordered; use when order does not matter and speed is priority TreeSet — O(log n); sorted; use when you need: • Iteration in sorted order • Range queries (subSet, headSet, tailSet) • Nearest-element lookups (floor, ceiling) • Removing the min/max efficiently
Common interview pattern: use a TreeSet (or PriorityQueue) to maintain a running sorted window, find the kth largest element, or solve interval-overlap problems.
import java.util.*;
// Interview pattern: sliding window median using two TreeSets
public class SlidingWindowMax {
// Find max in every window of size k — O(n log k) with TreeMap
public static int[] slidingMax(int[] nums, int k) {
int[] result = new int[nums.length - k + 1];
// TreeMap<value, count> to handle duplicates
TreeMap<Integer, Integer> window = new TreeMap<>();
for (int i = 0; i < nums.length; i++) {
// Add new element
window.merge(nums[i], 1, Integer::sum);
// Remove element going out of window
if (i >= k) {
int out = nums[i - k];
window.merge(out, -1, Integer::sum);
if (window.get(out) == 0) window.remove(out);
}
// Record max when window is full
if (i >= k - 1) {
result[i - k + 1] = window.lastKey(); // O(log k)
}
}
return result;
}
public static void main(String[] args) {
int[] nums = {1, 3, -1, -3, 5, 3, 6, 7};
System.out.println(Arrays.toString(slidingMax(nums, 3)));
// [3, 3, 5, 5, 6, 7]
}
}Interactive Visualization
Key Points to Remember
- TreeSet is backed by a TreeMap — O(log n) all ops; elements always in sorted order
- Equality in TreeSet is determined by compareTo (not equals) — compareTo==0 means duplicate
- floor/ceiling/lower/higher give O(log n) nearest-element lookups
- subSet/headSet/tailSet return live views — mutations propagate to the original
- pollFirst/pollLast remove and return boundary elements in O(log n)
- Use TreeSet over HashSet when sorted iteration or range queries are required
Practice TreeSet in the Playground
Run and modify code directly in your browser - no setup needed.
Interview Questions
Sign in to ask AriaWhat is the internal implementation of TreeSet?
What is the difference between TreeSet and HashSet?
How does TreeSet determine duplicates — equals() or compareTo()?
What is the difference between floor() and lower() in TreeSet?
How would you get the kth smallest element from a stream of numbers efficiently?
Ask Aria about TreeSet
Your personal AI tutor — ask anything about this concept