By WebNest Studio Engineering Team
Java - Core Tutorial
Set Interface: HashSet, LinkedHashSet, TreeSet
A Set is a collection that guarantees no duplicate elements — attempting to add an element that is already present (as determined by equals()) is silently ignored, and add() returns false. Java provides three principal implementations, and the one you choose determines what, if any, ordering guarantee you get.
Why it matters
A Set answers the question "have I seen this before?" in constant time, which a list cannot do. Removing duplicates, checking membership and finding what two groups have in common are all set operations. The three implementations differ only in the order they give back the elements and in what that order costs.
HashSet — No Order, Hash-Based
HashSet stores elements in a hash table and gives no guarantee about iteration order — the order can even change between runs. In exchange, add(), remove(), and contains() run in average O(1) time, because the element's hash code determines which bucket it belongs to directly. HashSet requires that elements have correct, consistent hashCode() and equals() implementations; getting these wrong breaks uniqueness silently.
LinkedHashSet — Insertion Order Preserved
LinkedHashSet extends HashSet but additionally maintains a doubly linked list running through all entries, so iteration order matches insertion order. It costs slightly more memory and a small constant-time overhead compared to HashSet, but is still O(1) average for the core operations. Choose it when you need set semantics (no duplicates) but also want predictable, reproducible iteration order.
TreeSet — Sorted Order
TreeSet is backed by a red-black tree and keeps its elements in sorted order at all times. Core operations (add, remove, contains) run in O(log n) time — slower than a hash-based set, but you gain sorted iteration plus navigation methods like first(), last(), higher(), and lower(). TreeSet requires that elements either implement Comparable, or that you supply a Comparator when constructing it — otherwise it throws ClassCastException at runtime on the first comparison.
- HashSet: no ordering guarantee, O(1) average, needs correct hashCode/equals.
- LinkedHashSet: insertion order preserved, O(1) average, slightly more overhead than HashSet.
- TreeSet: sorted order, O(log n), requires Comparable or a Comparator.
Time complexity
| Operation | Average | Worst case |
|---|---|---|
HashSet / LinkedHashSet add, contains, remove | O(1) | O(log n) when many elements share a bucket |
TreeSet add, contains, remove | O(log n) | O(log n) |
TreeSet first(), last() | O(log n) | O(log n) |
Example
Comparing iteration order across the three Set implementations
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo {
public static void main(String[] args) {
Set<String> hashSet = new HashSet<>();
hashSet.add("banana");
hashSet.add("apple");
hashSet.add("cherry");
System.out.println("HashSet (unordered): " + hashSet);
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("banana");
linkedHashSet.add("apple");
linkedHashSet.add("cherry");
System.out.println("LinkedHashSet (insertion order): " + linkedHashSet);
Set<String> treeSet = new TreeSet<>();
treeSet.add("banana");
treeSet.add("apple");
treeSet.add("cherry");
System.out.println("TreeSet (sorted order): " + treeSet);
}
}
HashSet (unordered): [banana, apple, cherry]
LinkedHashSet (insertion order): [banana, apple, cherry]
TreeSet (sorted order): [apple, banana, cherry]
Common Mistakes
- Relying on HashSet iteration order being consistent or meaningful — it is unspecified and implementation-dependent.
- Adding a custom object to a HashSet without overriding both hashCode() and equals(), which allows duplicate-looking objects to slip in.
- Putting elements with no natural ordering (and no Comparator supplied) into a TreeSet, which throws ClassCastException at runtime.
- Choosing TreeSet by default when sorted order is not actually needed, paying O(log n) instead of O(1) for no benefit.
Exercise
Print the first colour that appears a second time in the list. Use the value that add returns instead of calling contains first.
Expected output: blue
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class FirstDuplicate {
public static void main(String[] args) {
List<String> colours = List.of("red", "blue", "green", "blue", "red");
Set<String> seen = new HashSet<>();
for (String colour : colours) {
// TODO: add the colour to the set; if it was already there, print it and stop
}
}
}
Show hints
seen.add(colour)returnsfalsewhen the set already contains that element.- Use
breakto leave the loop after printing.
Show solution
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class FirstDuplicate {
public static void main(String[] args) {
List<String> colours = List.of("red", "blue", "green", "blue", "red");
Set<String> seen = new HashSet<>();
for (String colour : colours) {
if (!seen.add(colour)) { // false means it was already in the set
System.out.println(colour); // blue
break;
}
}
}
}
Quick quiz
1. Which Set returns its elements in the order they were added?
- A. HashSet
- B. LinkedHashSet
- C. TreeSet
- D. None of them
Show answer
B. LinkedHashSet keeps a linked list through its entries to remember insertion order.
2. What does set.add(x) return when x is already in the set?
- A. true
- B. null
- C. false
- D. It throws an exception
Show answer
C. The set is unchanged and add returns false.
3. What happens when you add objects of a class that is not Comparable to a TreeSet created with no comparator?
- A. They are stored in insertion order
- B. It does not compile
- C. They are sorted by hash code
- D. ClassCastException is thrown at runtime
Show answer
D. TreeSet has to compare elements to place them, and it casts them to Comparable to do so.
Interview questions
What is the difference between HashSet, LinkedHashSet and TreeSet?
Show answer
All three hold no duplicates. HashSet gives no ordering guarantee and has O(1) average operations. LinkedHashSet has the same speed and returns elements in insertion order. TreeSet keeps elements sorted, by their natural order or a Comparator, with O(log n) operations, and offers methods such as first(), headSet() and ceiling().
How does a HashSet decide that two elements are duplicates?
Show answer
It uses hashCode() to find the bucket and then equals() to compare with the elements already there. Two objects are duplicates only if their hash codes match and equals() returns true. A class that overrides equals() without hashCode() can therefore be stored twice in the same set.
Can a Set contain null?
Show answer
HashSet and LinkedHashSet allow one null. A TreeSet that uses natural ordering throws NullPointerException when null is added, because it has to call compareTo on the element.
Key Points to Remember
- HashSet: fastest (O(1) average), no ordering guarantee.
- LinkedHashSet: O(1) average with predictable insertion-order iteration.
- TreeSet: sorted order, O(log n), requires Comparable or a Comparator.
- All three enforce uniqueness via equals()/hashCode() (HashSet, LinkedHashSet) or compareTo()/Comparator (TreeSet).
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering