00:00

LinkedHashSet in Java – Complete Guide with Examples

LinkedHashSet is a Set that remembers the order in which elements were added. Like HashSet, it stores only unique elements and offers fast O(1) operations, but when you loop over it, the elements come back in insertion order.

It lives in java.util, extends HashSet, and has been available since JDK 1.4. This tutorial shows when to use it, how it works inside, and a few practical patterns built on it.

1. What Is a LinkedHashSet?

Think of a sign-in sheet at an event: each person signs once, and the sheet shows names in the order people arrived. A LinkedHashSet gives you exactly that: uniqueness plus a predictable order.

  • Unique elements, like every Set.
  • Insertion order is kept during iteration.
  • Fast: add, remove and contains are O(1) on average.
  • One null allowed.
  • Re-adding an existing element does not move it.
  • Not synchronized, with fail-fast iterators.
  • A SequencedSet since Java 21, with getFirst(), getLast() and reversed().

2. Class Hierarchy and Declaration

LinkedHashSet class hierarchy in Java
java.util.LinkedHashSet
public class LinkedHashSet<E> extends HashSet<E>
        implements SequencedSet<E>, Cloneable, java.io.Serializable

Before Java 21 it implemented Set instead of SequencedSet; the rest is unchanged.

3. LinkedHashSet vs HashSet in Action

Both sets receive the same names. Only the LinkedHashSet returns them in arrival order:

LinkedHashSetQuickStart.java
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

public class LinkedHashSetQuickStart {
    public static void main(String[] args) {
        String[] arrivals = {"Zara", "Aman", "Kiran", "Bela", "Aman"};

        Set<String> hash = new HashSet<>();
        Set<String> linked = new LinkedHashSet<>();
        for (String name : arrivals) {
            hash.add(name);
            linked.add(name);
        }
        System.out.println("HashSet:       " + hash);
        System.out.println("LinkedHashSet: " + linked + "  <- arrival order");
    }
}
Output
HashSet:       [Kiran, Aman, Bela, Zara]
LinkedHashSet: [Zara, Aman, Kiran, Bela]  <- arrival order

4. Constructors

ConstructorWhat it does
LinkedHashSet()Empty set with capacity 16 and load factor 0.75.
LinkedHashSet(int initialCapacity)Empty set with the given capacity.
LinkedHashSet(int initialCapacity, float loadFactor)Empty set with the given capacity and load factor.
LinkedHashSet(Collection<? extends E> c)A set with the unique elements of c, in c's iteration order.

Java 19 added LinkedHashSet.newLinkedHashSet(int numElements) to size the set for an expected number of elements.

5. What Happens When You Add an Element Again

Adding an element that is already present changes nothing, including its position. To move an element to the end, remove it and add it again:

ReinsertionOrder.java
import java.util.LinkedHashSet;
import java.util.Set;

public class ReinsertionOrder {
    public static void main(String[] args) {
        Set<String> steps = new LinkedHashSet<>();
        steps.add("design");
        steps.add("code");
        steps.add("test");
        System.out.println("Start:               " + steps);

        steps.add("design");                 // already present: position unchanged
        System.out.println("add(design) again:   " + steps);

        steps.remove("design");
        steps.add("design");                 // removed and added: now last
        System.out.println("remove + add:        " + steps);
    }
}
Output
Start:               [design, code, test]
add(design) again:   [design, code, test]
remove + add:        [code, test, design]

6. How LinkedHashSet Works Internally

A LinkedHashSet is a HashSet whose internal map is a LinkedHashMap instead of a HashMap. Every entry therefore lives in two structures at once:

  1. A hash table, which finds elements quickly by hash code (the O(1) part).
  2. A doubly linked list running through all entries in insertion order (the ordering part).

Adding an element puts it in its bucket and links it to the end of the list. Removing it unlinks it from both. Iteration simply follows the linked list from the first entry to the last, which also means iteration time depends only on the number of elements, not on the table capacity as in HashSet.

The cost of the extra links is a little more memory per element than a HashSet.

7. Removing Duplicates While Keeping Order

The most common use of LinkedHashSet: remove duplicates from data while keeping the order of first appearance.

UniqueInOrder.java
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

public class UniqueInOrder {
    public static void main(String[] args) {
        // 1. Remove duplicate orders but keep the order they arrived in
        List<Integer> orderIds = List.of(501, 502, 501, 503, 502, 504);
        System.out.println("Unique orders: " + new LinkedHashSet<>(orderIds));

        // 2. Unique characters of a word, in order of first appearance
        Set<Character> chars = new LinkedHashSet<>();
        for (char c : "programming".toCharArray()) chars.add(c);
        StringBuilder sb = new StringBuilder();
        for (char c : chars) sb.append(c);
        System.out.println("Unique letters: " + sb);
    }
}
Output
Unique orders: [501, 502, 503, 504]
Unique letters: progamin

8. Java 21: First, Last and Reversed

Since Java 21, LinkedHashSet implements SequencedSet, so you can work with both ends directly. Note that addFirst() and addLast() move an element that is already in the set.

SequencedSetDemo.java
import java.util.LinkedHashSet;
import java.util.List;

public class SequencedSetDemo {
    public static void main(String[] args) {
        // Java 21: LinkedHashSet is a SequencedSet
        LinkedHashSet<String> queue = new LinkedHashSet<>(List.of("B", "C", "D"));

        System.out.println("getFirst(): " + queue.getFirst() + ", getLast(): " + queue.getLast());

        queue.addFirst("A");           // new element at the front
        queue.addLast("B");            // existing element MOVES to the end
        System.out.println("After addFirst(A), addLast(B): " + queue);

        System.out.println("reversed(): " + queue.reversed());
        System.out.println("removeFirst(): " + queue.removeFirst() + " -> " + queue);
    }
}
Output
getFirst(): B, getLast(): D
After addFirst(A), addLast(B): [A, C, D, B]
reversed(): [B, D, C, A]
removeFirst(): A -> [C, D, B]

9. Practical Example: Recently Viewed Items

Online shops show "recently viewed" products: no duplicates, newest last, and only the last few. LinkedHashSet does this in a few lines:

RecentlyViewed.java
import java.util.LinkedHashSet;

public class RecentlyViewed {
    private final LinkedHashSet<String> items = new LinkedHashSet<>();
    private final int limit;

    RecentlyViewed(int limit) { this.limit = limit; }

    void view(String product) {
        items.remove(product);           // forget the old position
        items.add(product);              // newest goes to the end
        if (items.size() > limit) {
            items.remove(items.iterator().next());   // drop the oldest
        }
    }

    public static void main(String[] args) {
        RecentlyViewed recent = new RecentlyViewed(3);
        for (String p : new String[] {"phone", "laptop", "watch", "phone", "camera"}) {
            recent.view(p);
            System.out.println("viewed " + p + " -> " + recent.items);
        }
    }
}
Output
viewed phone -> [phone]
viewed laptop -> [phone, laptop]
viewed watch -> [phone, laptop, watch]
viewed phone -> [laptop, watch, phone]
viewed camera -> [watch, phone, camera]

For key–value caches with the same behaviour, LinkedHashMap in access-order mode with removeEldestEntry() is the classic LRU cache.

10. Common Methods

MethodDescription
add(e)Adds at the end if absent; returns false for a duplicate.
remove(o), contains(o)Remove or check an element (O(1)).
size(), isEmpty(), clear()Count, check and empty.
addAll, retainAll, removeAll, removeIfBulk operations; added elements go to the end in the source order.
iterator(), forEach(), stream()Visit elements in insertion order.
getFirst(), getLast()First or last element (Java 21).
addFirst(e), addLast(e)Add or move an element to the front or end (Java 21).
removeFirst(), removeLast()Remove and return the first or last element (Java 21).
reversed()A reverse-ordered view (Java 21).

11. HashSet vs LinkedHashSet vs TreeSet

FeatureHashSetLinkedHashSetTreeSet
OrderNoneInsertion orderSorted
PerformanceO(1)O(1), slightly slowerO(log n)
Iteration costO(n + capacity)O(n)O(n)
MemoryLowestMediumHighest
nullOneOneNo
SinceJDK 1.2JDK 1.4JDK 1.2

12. When to Use LinkedHashSet

  • You need unique values and a predictable order, for example items shown to users.
  • You remove duplicates from a list and want to keep the original order.
  • You want repeatable output in logs and tests, which HashSet does not give.
  • You need "recently used" or "first seen" behaviour.

Choose HashSet when order truly does not matter (slightly faster, less memory), and TreeSet when you need sorted order.

13. Thread Safety

LinkedHashSet is not synchronized. Wrap it with Collections.synchronizedSet(new LinkedHashSet<>()) and lock the set while iterating, or use CopyOnWriteArraySet, which also keeps insertion order, for small sets that are mostly read.

14. Summary

  • LinkedHashSet is a HashSet that keeps insertion order using a doubly linked list.
  • Operations are O(1); iteration is O(n) in insertion order.
  • Re-adding an existing element does not change its position.
  • It is ideal for removing duplicates while keeping order.
  • Java 21 added getFirst(), getLast(), addFirst(), addLast() and reversed().

Related Tutorials

Reference: Java SE 21 API: java.util.LinkedHashSet