HashSet vs TreeSet vs LinkedHashSet
MediumHashSet: O(1) average, no order, uses hashCode/equals. LinkedHashSet: same speed plus insertion order. TreeSet: O(log n), kept sorted by compareTo or a Comparator, and that comparison (not equals) decides what counts as a duplicate.
How it works
- Each set wraps a map. The elements are the map's keys and a shared dummy object is the value.
HashSet→HashMapLinkedHashSet→LinkedHashMapTreeSet→TreeMap(a red-black tree)
- HashSet finds a bucket from
hashCode()and checksequals().add,remove,containsare O(1) on average. Iteration order is unspecified and can change after a resize. - LinkedHashSet adds a doubly linked list through the entries, so iteration follows insertion order. Re-adding an existing element doesn't move it.
- TreeSet keeps elements sorted. Operations are O(log n). Two elements are duplicates when
compare(a, b) == 0, whateverequalssays. - Extra API.
TreeSetis aNavigableSet:floor,ceiling,headSet,tailSet,descendingSet. From Java 21,LinkedHashSetandTreeSetare bothSequencedSets withgetFirst(),getLast()andreversed().
Example
List<String> names = List.of("mira", "Zed", "ann", "mira", "Bo");
new HashSet<>(names); // e.g. [ann, Bo, mira, Zed] (order not guaranteed)
new LinkedHashSet<>(names); // [mira, Zed, ann, Bo]
new TreeSet<>(names); // [Bo, Zed, ann, mira] (uppercase sorts first)
// Comparator decides duplicates in a TreeSet
Set<String> tags = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
tags.addAll(List.of("Java", "java", "JAVA"));
tags.size(); // 1
// NavigableSet queries
TreeSet<Integer> slots = new TreeSet<>(List.of(9, 11, 14, 16));
slots.ceiling(12); // 14: next free slot at or after 12
slots.headSet(14); // [9, 11]Edge cases
HashSetandLinkedHashSetallow onenull.TreeSetwith natural ordering throwsNullPointerExceptiononnull.- A
TreeSetof a class that isn'tComparableand has noComparatorthrowsClassCastExceptionon the firstadd. - Mutating a field used by
hashCode()orcompareTo()after insertion makes the element unfindable. TreeSet.addFirst()throwsUnsupportedOperationException: sorted order is fixed, so you can't place an element.
Common mistakes
- Picking
TreeSet"to be safe" when you never need ordering. You pay O(log n) and a comparison per step. - Expecting
HashSetto keep insertion order because it happened to in a small test. - Using a comparator that is inconsistent with
equalsand losing elements without noticing.
Likely follow-up
"How would you get a thread-safe sorted set?" Use ConcurrentSkipListSet. It's sorted, lock-free for reads, and its iterators are weakly consistent. Collections.synchronizedSortedSet works too but locks the whole set.
Get every deep dive in the app
Coming soon to the App StoreComing soon to Google Play