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,removeandcontainsare O(1) on average. - One
nullallowed. - Re-adding an existing element does not move it.
- Not synchronized, with fail-fast iterators.
- A SequencedSet since Java 21, with
getFirst(),getLast()andreversed().
2. Class Hierarchy and Declaration
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:
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");
}
}
HashSet: [Kiran, Aman, Bela, Zara] LinkedHashSet: [Zara, Aman, Kiran, Bela] <- arrival order
4. Constructors
| Constructor | What 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:
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);
}
}
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:
- A hash table, which finds elements quickly by hash code (the O(1) part).
- 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.
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);
}
}
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.
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);
}
}
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:
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);
}
}
}
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
| Method | Description |
|---|---|
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, removeIf | Bulk 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
| Feature | HashSet | LinkedHashSet | TreeSet |
|---|---|---|---|
| Order | None | Insertion order | Sorted |
| Performance | O(1) | O(1), slightly slower | O(log n) |
| Iteration cost | O(n + capacity) | O(n) | O(n) |
| Memory | Lowest | Medium | Highest |
null | One | One | No |
| Since | JDK 1.2 | JDK 1.4 | JDK 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()andreversed().
Related Tutorials
- HashSet in Java
- TreeSet in Java
- LinkedHashMap in Java
- Difference between HashSet and LinkedHashSet
- Difference between LinkedHashSet and TreeSet
Reference: Java SE 21 API: java.util.LinkedHashSet
Frequently Asked Questions (FAQ)
Q1. What is a LinkedHashSet in Java?
LinkedHashSet is a class in java.util that extends HashSet and keeps elements in insertion order. It stores unique elements, allows one null, and offers O(1) add, remove and contains.
Q2. How does LinkedHashSet maintain insertion order?
It is backed by a LinkedHashMap, which links all entries in a doubly linked list in the order they were added. Iteration follows that list.
Q3. What is the difference between HashSet and LinkedHashSet?
Both store unique elements with O(1) operations. HashSet has no guaranteed order and uses a little less memory. LinkedHashSet keeps insertion order and iterates in O(n) regardless of capacity.
Q4. Does re-inserting an element change its position in a LinkedHashSet?
No. add() on an existing element returns false and leaves its position unchanged. Remove it first and add it again to move it to the end, or use addLast() on Java 21.
Q5. Does LinkedHashSet allow null?
Yes, one null element, in the position where it was first added.
Q6. Is LinkedHashSet sorted?
No. It keeps insertion order, not sorted order. Use TreeSet for a set that is always sorted.
Q7. Is LinkedHashSet slower than HashSet?
Slightly, because each add and remove also updates the linked list, and each entry uses more memory. Iteration can actually be faster than in a sparsely filled HashSet, because it walks only the existing entries.
Q8. How do I remove duplicates from a list but keep the order?
List<String> unique = new ArrayList<>(new LinkedHashSet<>(list));
The stream version list.stream().distinct().toList() gives the same result.
Q9. How do I get the first or last element of a LinkedHashSet?
On Java 21 and later, call getFirst() or getLast(). On older versions, use set.iterator().next() for the first element, and loop to the end (or copy into a list) for the last.
Q10. Can I access LinkedHashSet elements by index?
No, it has no get(index) method. Copy it into a list (new ArrayList<>(set)) if you need positions.
Q11. Is LinkedHashSet thread-safe?
No. Use Collections.synchronizedSet(new LinkedHashSet<>()) with manual locking during iteration, or CopyOnWriteArraySet, which also preserves insertion order.
Q12. Does LinkedHashSet support access order like LinkedHashMap?
No. LinkedHashSet always uses insertion order; it has no access-order constructor. To build an LRU structure, use LinkedHashMap with accessOrder = true, or remove and re-add elements in a LinkedHashSet as shown in the "recently viewed" example.
Q13. What is the difference between LinkedHashSet and TreeSet?
LinkedHashSet keeps insertion order with O(1) operations and allows null. TreeSet keeps sorted order with O(log n) operations, does not allow null, and provides navigation methods such as floor() and ceiling().
Q14. What is the default capacity of a LinkedHashSet?
16 buckets with a load factor of 0.75, the same as HashSet. The table doubles once the set holds more than 12 elements.
Q15. Does LinkedHashSet use equals() and hashCode()?
Yes, exactly like HashSet. Override both in your own classes, keep them consistent, and do not change an element's hash fields while it is in the set.
Q16. How do I iterate over a LinkedHashSet in reverse?
On Java 21, use the reversed() view: for (String s : set.reversed()) { ... }. On older versions, copy into a list and use Collections.reverse() or a ListIterator from the end.
Q17. When was LinkedHashSet introduced?
In JDK 1.4, together with LinkedHashMap. Java 19 added newLinkedHashSet(), and Java 21 made it a SequencedSet.
Q18. Is the LinkedHashSet iterator fail-fast?
Yes. Changing the set structurally during iteration, except through the iterator's own remove(), throws ConcurrentModificationException.
Q19. What does addAll() do to the order?
New elements are appended in the iteration order of the collection you pass in. Elements that are already present keep their original position.
Q20. When should I prefer LinkedHashSet over HashSet?
Whenever the order of elements is visible or matters: output shown to users, logs, test assertions, JSON responses or step lists. The small extra cost is usually worth the predictable behaviour.