Java sets store unique elements. HashSet, LinkedHashSet and TreeSet differ primarily in how they find elements and which iteration order they promise. The correct choice depends on whether you need arbitrary uniqueness, insertion order or a sorted sequence.
Review the related foundation lesson when you need a prerequisite. The complete programs below use Java 17-compatible syntax.
Uniqueness rules
Set prevents duplicate elements according to its equality or comparison rules. It is useful when membership matters more than numbered positions.
HashSet uses hashing to locate elements and typically offers expected constant-time basic operations with suitably distributed hashes. It does not promise iteration order. Elements considered equal must have equal hash codes, although unequal elements may share a hash. If a mutable element changes fields used by equals or hashCode after insertion, lookups can fail because its stored location no longer matches its current hash.
Hash and insertion order
HashSet gives expected fast lookup and does not promise iteration order. LinkedHashSet preserves insertion order for predictable presentation.
LinkedHashSet combines uniqueness with encounter order based on insertion. Adding an already present element does not move that element to the end. Removing it and then adding it again places it at the end in these Java 17 examples. It is useful when a de-duplicated display should follow the original appearance order rather than an unspecified hashing order.
Sorted-set comparison
TreeSet maintains sorted order and provides navigational operations. Its comparator determines when elements count as duplicates, so ordering should agree with intended equality.
TreeSet orders elements by natural order or a supplied Comparator. For this set, comparison returning zero determines whether values occupy the same set position. A case-insensitive comparator can therefore treat differently cased strings as duplicates even though String.equals would distinguish them. An ordering inconsistent with equals can produce surprising set-contract behavior; choose a comparator aligned with the intended notion of uniqueness.
Stable keys and implementation-specific input rules
Mutable fields used in equals, hashCode or comparison can break set behavior when changed after insertion. Keep keys stable or remove and reinsert them deliberately.
Set.add returns whether the set changed. contains checks membership, and remove reports whether an element was removed. HashSet and LinkedHashSet permit a null element, while ordinary naturally ordered TreeSet values must be mutually comparable and cannot use null. Immutable Set.of rejects null and duplicate arguments. These input rules come from the implementation or factory, not merely the Set variable type.
Running the examples
Save name.java, compile it with javac --release 17 name.java, and run java name. Use each program's own public class name and filename.
How BandSetOrdering produces its output
LinkedHashSet receives Teal, Amber and Teal. The repeated Teal adds no new element and does not move the original one, so insertion-ordered traversal displays Teal before Amber. Constructing a TreeSet copies those distinct values into natural String order, displaying Amber before Teal. The two outputs now make the ordering difference visible while both collections contain exactly the same two values.
How UniqueVisits produces its output
The first West and then East establish encounter order. Adding West again finds an equal element already present, so it does not insert a duplicate or move West. The set has two elements and prints their original insertion sequence. HashSet would retain the same membership without guaranteeing this display order.
How CaseInsensitiveSet produces its output
The comparator treats Lina and lina as equal for ordering, so the second add returns false. Only one entry remains. String.equals would consider these two spellings different, which demonstrates why a TreeSet's comparator must be chosen with its intended uniqueness rule in mind rather than viewed as display formatting alone.
Define equality before building a set
A custom member type placed in HashSet should override equals and hashCode consistently when uniqueness is based on an identifier. Two members considered equal must produce equal hash codes; a matching hash alone does not establish equality. An immutable identifier makes that promise easier to preserve after insertion. For a TreeSet, the comparator must express the intended identity relationship as well as order. For practice, compare a set of case-sensitive strings with a case-insensitive TreeSet. Explain why the two sets can have different sizes for the same source data. The difference is a declared comparison policy, not a failure of duplicate removal.
Java Summary
- Set prevents duplicate elements according to its equality or comparison rules. It is useful when membership matters more than numbered positions.
- HashSet gives expected fast lookup and does not promise iteration order. LinkedHashSet preserves insertion order for predictable presentation.
- TreeSet maintains sorted order and provides navigational operations. Its comparator determines when elements count as duplicates, so ordering should agree with intended equality.
- Mutable fields used in equals, hashCode or comparison can break set behavior when changed after insertion. Keep keys stable or remove and reinsert them deliberately.
- Continue with Java exercises, Java quizzes and the Java study roadmap.
Java Examples
Each example shows the code, the output it produces and what each part does.
Java HashSet, TreeSet and LinkedHashSet in a complete program
public class BandSetOrdering {
public static void main(String[] args) {
java.util.Set<String> bands = new java.util.LinkedHashSet<>();
bands.add("Teal");
bands.add("Amber");
bands.add("Teal");
System.out.println(bands);
System.out.println(new java.util.TreeSet<>(bands));
}
}[Teal, Amber]
[Amber, Teal]Line-by-line explanation
- Line 7Evaluates
bandsand prints[Teal, Amber]. - Line 8Evaluates
new java.util.TreeSet<>(bands)and prints[Amber, Teal].
Insertion order survives duplicate adds
public class UniqueVisits {
public static void main(String[] args) {
java.util.Set<String> places = new java.util.LinkedHashSet<>();
places.add("West");
places.add("East");
places.add("West");
System.out.println(places);
System.out.println(places.size());
}
}[West, East]
2Line-by-line explanation
- Line 7Evaluates
placesand prints[West, East]. - Line 8Evaluates
places.size()and prints2.
Comparison controls TreeSet uniqueness
public class CaseInsensitiveSet {
public static void main(String[] args) {
java.util.Set<String> names = new java.util.TreeSet<>(String.CASE_INSENSITIVE_ORDER);
System.out.println(names.add("Lina"));
System.out.println(names.add("lina"));
System.out.println(names.size());
}
}true
false
1Line-by-line explanation
- Line 4Evaluates
names.add("Lina")and printstrue. - Line 5Evaluates
names.add("lina")and printsfalse. - Line 6Evaluates
names.size()and prints1.
Java FAQ
Why does HashSet output change after edits?
Its iteration order is unspecified and can depend on hashing and internal table structure. Do not rely on an observed order, even if it appears stable in one run. Choose LinkedHashSet or TreeSet when order is part of the requirement.
Can I change an object already inside a set?
Changing unrelated state may be fine, but changing equality, hash or ordering fields can violate the set's assumptions. Remove the object before such a change and reinsert afterward, or prefer immutable elements for identity-defining data.
How do I get a set's elements in sorted order?
Copy them into a TreeSet, as in new TreeSet<>(hashSet), or sort a stream: set.stream().sorted().toList(). If the set should always stay sorted, create a TreeSet from the start instead of a HashSet.
How do I find the common elements of two sets?
Copy one set and call retainAll with the other: the copy keeps only shared elements, so {1, 2, 3} and {2, 3, 4} give {2, 3}. addAll gives the union and removeAll the difference. Work on a copy, because these methods change the set they're called on.
Can a Java set contain null?
HashSet and LinkedHashSet allow a single null element. A TreeSet that uses natural ordering throws a NullPointerException, because it can't compare null, and Set.of rejects null entirely.
Java Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Which set preserves insertion order?
What decides TreeSet uniqueness?
Java Quiz
2 questions to check what you learned.
What does adding an existing equal element return?
- false
- true
- The existing index
Why avoid mutating hash-defining fields after insertion?
- The stored bucket may no longer match the element's hash
- Sets cannot contain objects
- Every mutation automatically removes the element