Set
The Set interface — no duplicates, fast membership testing. HashSet, LinkedHashSet, TreeSet — when to use each.
Last reviewed: January 2025
🔍 What Is It?
Set Interface
java.util.Set extends Collection but guarantees no duplicates:
- →add(E e) — adds element; returns false if already present
- →contains(Object o) — O(1) for HashSet, O(log n) for TreeSet
- →remove(Object o) — removes element
- →No index-based access (no get(int index))
Key Implementations:
- →HashSet — backed by HashMap; O(1) average add/contains/remove; no ordering guarantee
- →LinkedHashSet — HashSet + doubly-linked list; O(1) operations; preserves insertion order
- →TreeSet — backed by TreeMap (Red-Black tree); O(log n) operations; always sorted; elements must be Comparable or provide Comparator
- →EnumSet — specialized for enum types; extremely fast (bitset internally)
- →Set.of() — immutable set (Java 9+)
- →CopyOnWriteArraySet — thread-safe; backed by CopyOnWriteArrayList
🎯 Why Do We Need It?
Sets solve uniqueness problems:
- →Deduplication — remove duplicates from a list
- →Membership testing — is this user in the admin set? is this email already registered?
- →Set operations — union, intersection, difference (for business logic)
- →Tag systems — user has tags: Set<String> tags; fast contains() check
Critical: for HashSet to work correctly, elements must implement equals() and hashCode() consistently.
🏗️ What Happens in Real Projects?
Common enterprise patterns:
// Deduplication
List<String> withDups = Arrays.asList("a", "b", "a", "c", "b");
Set<String> unique = new LinkedHashSet<>(withDups); // preserves order
List<String> deduped = new ArrayList<>(unique);
// Permission checking
Set<Permission> userPermissions = user.getPermissions();
if (userPermissions.contains(Permission.ADMIN)) { ... }
// Find common elements (intersection)
Set<String> teamA = Set.of("alice", "bob", "charlie");
Set<String> teamB = Set.of("bob", "charlie", "diana");
Set<String> both = new HashSet<>(teamA);
both.retainAll(teamB); // {bob, charlie}⚙️ How It Works
HashSet:
Internally a HashMap<E, PRESENT> — the element is the key. Uses hashCode() to find the bucket, then equals() to check for duplicates. Requires both to be consistent.
TreeSet:
Internally a TreeMap. Elements are sorted using natural ordering (Comparable) or a provided Comparator. Does NOT use equals()/hashCode() — uses compareTo() for equality. Two elements where compareTo() returns 0 are considered equal even if equals() returns false.
Critical: equals() and hashCode() contract:
If a.equals(b) is true, then a.hashCode() must equal b.hashCode(). If you override one, you must override both.
💻 Example
Set Operations in Enterprise Code — Practical Set usage for deduplication, membership, and set operations.
🤔 Common Confusions
❓ Why does my Set contain "duplicates" even though I added the same object?
You probably did not override equals() and hashCode() in your class. HashSet uses these to detect duplicates. Without overriding, two objects with the same data are considered different (default Object.equals() compares references). Always override both equals() and hashCode() for objects used in Sets or as Map keys.
❓ Why does TreeSet use compareTo() instead of equals() for duplicates?
TreeSet uses compareTo() (or Comparator.compare()) for all comparisons — including equality. If compareTo() returns 0, TreeSet considers them equal and rejects the second element. This can cause bugs if your compareTo() and equals() are inconsistent. The Comparable contract says: (a.compareTo(b) == 0) should be consistent with a.equals(b).
🚨 Common Production Issues
Mutable objects in HashSet — if you modify an object after adding it to a HashSet (changing the fields used in hashCode), the set cannot find the object anymore. Never mutate objects stored in a HashSet.
Missing hashCode override — if you override equals() but not hashCode(), two equal objects can end up in different buckets. Always override both together.
✅ Best Practices
Always override equals() and hashCode() together for objects used in Sets.
Use LinkedHashSet when you need deduplication with preserved insertion order.
Use TreeSet when you need a sorted set with navigation operations.
Use EnumSet for sets of enum values — it is the fastest possible implementation.
Use Set.of() for small immutable sets (constants, test data).
🏛️ Architect's Note
In domain modeling, Sets are natural for many-to-many relationships: User has Set<Role>, Order has Set<Tag>. In JPA, @ManyToMany relationships are typically modeled as Set (not List) to avoid duplicate join records. However, be careful with HashSet in JPA entities — Hibernate requires equals/hashCode based on a business key, not the generated database ID.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
Core Java Interview Prep
Practice interview questions that connect directly to this technology track.
↗ Where this topic fits
Core Java Technology Guide
Return to the Core Java learning hub.
Backend Engineer Career Path
A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Sources
Sources / References
Use these Core Java references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide Core Java learning path
Browse the full Core Java topic collection and learning order on SplashRide.
Core Java Interview Prep
Practice Core Java interview questions and scenario-based answers.
Backend Engineer Career Path
A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
List
The List interface — ordered, indexed, allows duplicates. When to use ArrayList vs LinkedList, and the patterns senior developers rely on.
Java Map Interface Explained: HashMap, LinkedHashMap, and TreeMap
Learn the Java Map interface with HashMap, LinkedHashMap, TreeMap, ConcurrentHashMap, key-value lookup, ordering, performance, and real-world examples.