Course contents

How HashSet, LinkedHashSet and TreeSet work

HashSet, LinkedHashSet and TreeSet internals, ordering, equality contracts, null handling, navigable operations, EnumSet and complexity trade-offs.

PremiumMust know for interviewsLesson14 min readCoreReviewed Oct 2026 · Java 21
On this page
  1. Picture it first: three guest lists
  2. HashSet under the hood
  3. LinkedHashSet: uniqueness plus insertion order
  4. TreeSet: sorted uniqueness and navigation
  5. Nulls, EnumSet and the decision table
  6. How to say it in the interview

🧺 What are HashSet, LinkedHashSet and TreeSet?

A Set is a collection that keeps unique elements. HashSet is the everyday membership set, LinkedHashSet keeps unique elements in encounter order, and TreeSet keeps them sorted. If product names arrive as ["mouse", "keyboard", "mouse"], a set stores two names, not three.

For this lesson, we'll focus on how the three main set implementations work in Java 21, why their equality rules differ, and which one I would choose in common interview scenarios: unique product names, sign-up order for unique user IDs, sorted unique student IDs, and enum roles. Interviewers ask this because sets look small from the API, but they reveal whether you understand maps, equality, ordering and mutation.

Below the line (out of scope)

The 30-second answer

HashSet is backed by a HashMap<E,Object>: the set element is stored as the map key and every key points to the same dummy PRESENT object. add(e) is essentially map.put(e, PRESENT) == null, so it returns true only when the key was absent. LinkedHashSet uses a LinkedHashMap, so it has hash-table lookup plus insertion-order iteration and, since Java 21, SequencedSet methods like getFirst, getLast, addFirst and reversed(). TreeSet uses a TreeMap, so elements are ordered by Comparable or a Comparator, with O(log n) add, remove, contains and nearest-match operations like floor and ceiling. HashSet and LinkedHashSet allow one null; TreeSet with natural ordering rejects null; EnumSet is the best set for enum constants because it is a bit vector.

What you’ll learn

  • Explain why a HashSet is a **HashMap with dummy values** and what add() returns
  • Use the **equals/hashCode contract** safely and avoid the mutable-key bug
  • Choose HashSet, LinkedHashSet, TreeSet or EnumSet based on order and lookup cost
  • Describe Java 21 SequencedSet methods on LinkedHashSet, including addFirst, getLast and reversed()
  • Use TreeSet with Comparable or Comparator, and spot comparators that are inconsistent with equals
  • Apply NavigableSet methods like floor, ceiling, subSet, descendingSet and pollFirst

Interview radar

Asked very often: How does HashSet detect duplicates, and why does mutating a stored object break lookup? Senior rounds probe: Why can a TreeSet drop two unequal objects when the comparator returns 0? Production angle: A deduplication job starts emitting duplicates or leaking memory because mutable IDs were inserted into a hash-based set.

01Picture it first: three guest lists

Think of sets as three guest lists at an event. HashSet is the bouncer's stamp book: it answers "have I seen this person?" without caring about the line order. LinkedHashSet is the same stamp book plus a clipboard that records the first arrival order. TreeSet is a sorted register that keeps names in alphabetical or numeric order as people arrive.

The first picture shows the key trick behind HashSet: it is a map wearing a set-shaped jacket.

Fig. 1

A HashSet stores each element as a key in an internal HashMap, and every key points to the same dummy PRESENT value

A HashSet stores each element as a key in an internal HashMap, and every key points to the same dummy PRESENT value

Now compare iteration order. Add the same five numbers to each set and ask what a for loop sees.

Fig. 2

HashSet, LinkedHashSet and TreeSet receive the same inserted values, then iterate in unspecified hash order, insertion order and sorted order

HashSet, LinkedHashSet and TreeSet receive the same inserted values, then iterate in unspecified hash order, insertion order and sorted order

Notice three things:

  • HashSet optimizes membership, not human-readable order.
  • LinkedHashSet gives deterministic insertion order without sorting.
  • TreeSet gives sorted order and range queries, but pays O(log n) per update.

02HashSet under the hood

Try it yourself first

Before reading on, predict the three printed values. Why does the second add return false?

import java.util.HashSet;
import java.util.Set;

public class UniqueProductNames {
    public static void main(String[] args) {
        Set<String> names = new HashSet<>();

        System.out.println(names.add("keyboard"));
        System.out.println(names.add("mouse"));
        System.out.println(names.add("keyboard"));
        System.out.println(names);
    }
}

The first two calls print true; the third prints false. The set already contains an equal key, so the structure is unchanged. The final order is deliberately not promised, so do not write a test that expects [keyboard, mouse].

OpenJDK's HashSet has this shape:

private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();

public boolean add(E e) {
    return map.put(e, PRESENT) == null;
}

That line is the whole idea. A HashMap already knows how to store unique keys, spread hashes, handle collisions, resize and treeify crowded bins. HashSet reuses all of that and ignores the map value.

Notice the interaction:

  • contains(e) delegates to map.containsKey(e).
  • remove(e) removes the map key and returns whether the dummy value was present.
  • The element's hashCode() picks the bucket, then equals() confirms the match inside the bucket.
  • Expected add, remove and contains are O(1); under severe collisions, Java 8+ tree bins can make a crowded bucket O(log n) once the table is large enough.

This is why the usual product-name question is a HashSet question. If the requirement is "store unique product names and test membership", HashSet<String> is the default. If the requirement also says "print them in the order first seen", use LinkedHashSet<String> instead.

The equals and hashCode contract

Hash-based sets depend on one contract: equal objects must have equal hash codes. Unequal objects may collide, but equal objects cannot be sent to different buckets. If equals() says two users are the same email but hashCode() uses a database id, your set will behave like it is haunted.

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

final class ProductId {
    private final String value;

    ProductId(String value) {
        this.value = value;
    }

    @Override public boolean equals(Object other) {
        return other instanceof ProductId id && Objects.equals(value, id.value);
    }

    @Override public int hashCode() {
        return Objects.hash(value);
    }
}

public class ProductIdSet {
    public static void main(String[] args) {
        Set<ProductId> seen = new HashSet<>();
        seen.add(new ProductId("SKU-7"));
        System.out.println(seen.contains(new ProductId("SKU-7"))); // true
    }
}

Records are often the cleanest way to make set elements because they generate consistent equals() and hashCode() from final components. We cover the contract more deeply in The equals() and hashCode() contracts.

The mutable-key bug

Try it yourself first

Read the next program without running it. Why can a set of size 1 say it does not contain the exact object you inserted?

Premium lesson

Keep reading with the Java Pass

The rest of this lesson is part of Java One-Stop Interview Prep: in-depth explanations, diagrams, model answers and how to say them in the interview.

  • LinkedHashSet: uniqueness plus insertion order
  • TreeSet: sorted uniqueness and navigation
  • Nulls, EnumSet and the decision table
  • How to say it in the interview

From ₹199 · one-time payment · No auto-renewal

Practise this topicSets: interview questions & scenarios
Further reading (7)