Set Duplicate Prevention
Fast recall
Quick revision
Core answer
Set rejects an element when its implementation's equality rule says an equivalent element is already present. HashSet and LinkedHashSet use hashCode() to find candidates and equals() to match them. TreeSet uses natural ordering or a Comparator, where a comparison result of zero means the elements are the same for that set. add() returns false when no change was made.Understanding the Set contract and how equals/hashCode drive duplicate detection
Not realizing that custom objects without proper equals() and hashCode() will be treated as unique even if logically equal
Show a concrete example where a custom class without equals/hashCode allows duplicates in a HashSet
Interview-ready guide
Interview answer
A Set checks whether an equivalent element is already present and leaves the set unchanged if it is. For HashSet and LinkedHashSet, hashCode narrows the search and equals confirms the match, so equal custom objects must produce equal hashes.
TreeSet is different: its natural ordering or Comparator decides uniqueness, and comparison result zero means the value is already represented. That means a comparator inconsistent with equals can make TreeSet reject two objects that a HashSet would keep separately. In every case, add() returns false when the set did not change.
Set Duplicate Prevention
Direct Answer
A Set rejects an element when its implementation's equality rule says an equivalent element is already present. HashSet and LinkedHashSet use hashCode() to find candidates and equals() to match them. TreeSet uses natural ordering or a Comparator, where a comparison result of zero means the elements are the same for that set. add() returns false when no change was made.
Code Example
// Without equals/hashCode - allows duplicates!
class OrderBroken {
Long id;
String item;
OrderBroken(Long id, String item) { this.id = id; this.item = item; }
}
// Proper implementation prevents duplicates
record Order(Long id, String item) {} // records auto-generate equals/hashCode
var brokenSet = new HashSet<OrderBroken>();
brokenSet.add(new OrderBroken(1L, "Laptop"));
brokenSet.add(new OrderBroken(1L, "Laptop")); // both added!
System.out.println(brokenSet.size()); // prints 2 - duplicates allowed
var properSet = new HashSet<Order>();
properSet.add(new Order(1L, "Laptop"));
boolean added = properSet.add(new Order(1L, "Laptop")); // returns false
System.out.println(properSet.size()); // prints 1 - duplicate rejected
System.out.println(added); // false - element already exists
Common Mistakes & Pitfalls
- Overriding equals() without hashCode(): Freshers define logical equality but forget
hashCode, breaking the contract — equal objects return different hash codes, so theHashSetcannot find duplicates and stores them in different buckets. - Using mutable objects in Sets: If you add an object then modify a field used in
hashCode, its hash changes but it stays in the old bucket — nowcontainsandremovecan't find it, and duplicates creep in. - Comparing objects with ==: Freshers write
if (set.contains(order))expecting reference equality, not realizing theSetcallsequalsfor value-based comparison.
Check your understanding
Answer these without looking back at the article.
- What if equals() and hashCode() are not overridden for objects in a HashSet?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.