HashSet
HashSet is one of the most commonly used implementations of the Set interface in the Java Collections Framework. It stores unique elements and provides fast performance for basic operations using hashing. This is a very high-frequency interview topic.
What Is HashSet?
- Implementation of the Set interface
- Stores unique elements only
- Does not maintain insertion order
- Allows at most one null
- Part of java.util package
Set<String> set = new HashSet<>();
Position in Collection Hierarchy
Iterable
└── Collection
└── Set
└── HashSet
How HashSet Works Internally (Interview Favorite)
- Backed by a HashMap internally
- Elements stored as keys
- Dummy object used as value
private static final Object PRESENT = new Object();
- ✔ Fast lookup
- ✔ No duplicate keys allowed
Key Characteristics of HashSet
- Unordered (no guarantee of order)
- Average time complexity O(1)
- Uses hashCode() and equals()
- Not synchronized (not thread-safe)
Creating a HashSet
HashSet<Integer> set = new HashSet<>();
With Initial Capacity & Load Factor
HashSet<Integer> set = new HashSet<>(16, 0.75f);
- Default capacity = 16
- Default load factor = 0.75
Commonly Used Methods
set.add("Java");
set.remove("Java");
set.contains("Java");
set.size();
set.isEmpty();
Duplicate Handling Example
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("Java");
System.out.println(set); // [Java]
- ✔ Duplicate ignored
- ✔ No exception thrown
Importance of equals() and hashCode() (Critical)
HashSet uniqueness depends on:
- hashCode() → bucket location
- equals() → equality check
class Employee {
int id;
}
⚠️ Without overriding both methods, duplicates may be stored logically.
Null Handling
- Allows one null element
set.add(null);
set.add(null); // ignored
Performance Complexity
| Operation | Time Complexity |
|---|---|
| add | O(1) average |
| remove | O(1) |
| contains | O(1) |
| iteration | O(n) |
HashSet vs LinkedHashSet vs TreeSet
| Feature | HashSet | LinkedHashSet | TreeSet |
|---|---|---|---|
| Order | No | Insertion | Sorted |
| Performance | Fastest | Slightly slower | Slowest |
| Null allowed | One | One | ❌ No |
| Internal DS | HashMap | LinkedHashMap | Red-Black Tree |
Thread Safety
- Not thread-safe
Thread-safe Alternatives: Collections.synchronizedSet(), CopyOnWriteArraySet
When to Use HashSet
- Need unique elements
- Fast lookup required
- Order does not matter
- Membership testing
Common Beginner Mistakes
- Expecting insertion order
- Forgetting to override equals() and hashCode()
- Using mutable objects as elements
- Using HashSet in concurrent scenarios without synchronization
Interview-Ready Answers
Short Answer
HashSet is a Set implementation that stores unique elements using hashing.
Detailed Answer
In Java, HashSet implements the Set interface and uses a HashMap internally to store elements as keys. It ensures uniqueness using hashCode() and equals(), provides constant-time performance for basic operations, and does not maintain insertion order.
Key Takeaway
Use HashSet when uniqueness and performance matter more than order. Proper implementation of equals() and hashCode() is essential for correctness.
HashSet Examples
1. Creating a HashSet
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("API");
System.out.println(set);
}
}
Output
[Java, API]
2. HashSet Does Not Allow Duplicates
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<>();
set.add(10);
set.add(10);
set.add(20);
System.out.println(set);
}
}
Output
[10, 20]
3. No Guaranteed Order in HashSet
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("B");
set.add("A");
set.add("C");
System.out.println(set);
}
}
Explanation
Order may vary on each run.
4. HashSet Allows One null
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add(null);
set.add(null);
set.add("Java");
System.out.println(set);
}
}
Output
[null, Java]
5. Checking Element Existence (contains)
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>(Arrays.asList("Java", "API"));
System.out.println(set.contains("Java"));
}
}
Output
true
6. Removing Elements
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3));
set.remove(2);
System.out.println(set);
}
}
Output
[1, 3]
7. Iterating Using for-each
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>(Arrays.asList("A", "B", "C"));
for (String s : set) {
System.out.println(s);
}
}
}
8. Iterating Using Iterator
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<>(Arrays.asList(10, 20, 30));
Iterator<Integer> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
9. Removing While Iterating (Correct Way)
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3));
Iterator<Integer> it = set.iterator();
while (it.hasNext()) {
if (it.next() == 2) {
it.remove();
}
}
System.out.println(set);
}
}
Output
[1, 3]
10. Converting List to HashSet (Remove Duplicates)
import java.util.*;
class Demo {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 2, 3);
HashSet<Integer> set = new HashSet<>(list);
System.out.println(set);
}
}
Output
[1, 2, 3]
11. Converting HashSet to List
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>(Arrays.asList("A", "B"));
List<String> list = new ArrayList<>(set);
System.out.println(list);
}
}
12. isEmpty() and size()
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
System.out.println(set.isEmpty());
set.add("Java");
System.out.println(set.size());
}
}
Output
true
1
13. HashSet with Custom Objects (Without equals/hashCode)
class User {
int id;
User(int id) { this.id = id; }
}
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<User> set = new HashSet<>();
set.add(new User(1));
set.add(new User(1));
System.out.println(set.size());
}
}
Output
2
14. HashSet with Custom Objects (With equals & hashCode)
class User {
int id;
User(int id) { this.id = id; }
public boolean equals(Object o) {
return this.id == ((User)o).id;
}
public int hashCode() {
return id;
}
}
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<User> set = new HashSet<>();
set.add(new User(1));
set.add(new User(1));
System.out.println(set.size());
}
}
Output
1
15. Internal Working (Conceptual Example)
HashSet<String> set = new HashSet<>();
set.add("Java");
Explanation
- Uses HashMap internally
- Elements stored as keys
- Dummy value is used internally
16. HashSet vs LinkedHashSet (Order)
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<String> h = new HashSet<>();
h.add("B");
h.add("A");
LinkedHashSet<String> l = new LinkedHashSet<>();
l.add("B");
l.add("A");
System.out.println(h);
System.out.println(l);
}
}
Output
[A, B]
[B, A]
17. Thread-Safe HashSet
import java.util.*;
class Demo {
public static void main(String[] args) {
Set<String> set = Collections.synchronizedSet(new HashSet<>());
set.add("Safe");
System.out.println(set);
}
}
18. retainAll() – Intersection
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<Integer> s1 = new HashSet<>(Arrays.asList(1, 2, 3));
HashSet<Integer> s2 = new HashSet<>(Arrays.asList(2, 3, 4));
s1.retainAll(s2);
System.out.println(s1);
}
}
Output
[2, 3]
19. addAll() – Union
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<Integer> s1 = new HashSet<>(Arrays.asList(1, 2));
HashSet<Integer> s2 = new HashSet<>(Arrays.asList(2, 3));
s1.addAll(s2);
System.out.println(s1);
}
}
Output
[1, 2, 3]
20. Interview Summary – HashSet
import java.util.*;
class Demo {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("Unique");
set.add("Unique");
System.out.println(set);
}
}
Key Points
- No duplicates
- Allows one null
- No insertion order
- Backed by HashMap
- Depends on hashCode() & equals()