Java HashSet, TreeSet and LinkedHashSet

Java sets store unique elements.

Lesson 52 of 127Intermediate13 min read

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.

Example 1

Java HashSet, TreeSet and LinkedHashSet in a complete program

Java
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));
    }
}
Output
[Teal, Amber]
[Amber, Teal]
Line-by-line explanation
  1. Line 7Evaluates bands and prints [Teal, Amber].
  2. Line 8Evaluates new java.util.TreeSet<>(bands) and prints [Amber, Teal].
Example 2

Insertion order survives duplicate adds

Java
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());
    }
}
Output
[West, East]
2
Line-by-line explanation
  1. Line 7Evaluates places and prints [West, East].
  2. Line 8Evaluates places.size() and prints 2.
Example 3

Comparison controls TreeSet uniqueness

Java
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());
    }
}
Output
true
false
1
Line-by-line explanation
  1. Line 4Evaluates names.add("Lina") and prints true.
  2. Line 5Evaluates names.add("lina") and prints false.
  3. Line 6Evaluates names.size() and prints 1.

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.

Multiple choiceeasy

Which set preserves insertion order?

Multiple choicemedium

What decides TreeSet uniqueness?

Java Quiz

2 questions to check what you learned.

  1. What does adding an existing equal element return?

    • false
    • true
    • The existing index
  2. 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