๐ What Is a HashSet?
A HashSet is a collection in Java that stores unique elements โ no duplicates allowed.
Itโs part of the java.util package and is backed by a HashMap internally.
Think of it like a bag of unique cards ๐ด โ if you try to add the same card again, it just ignores it.
โ๏ธ Quick Example import java.util.HashSet; public class HashSetExample { public static void main(String[] args) { HashSet<String> countries = new HashSet<>(); countries.add("Japan"); countries.add("Canada"); countries.add("Japan"); // duplicate ignored System.out.println(countries); // [Japan, Canada] System.out.println("Contains Canada? " + countries.contains("Canada")); // true } } โ
Output:
[Japan, Canada] Contains Canada? true ๐ง Notice how โJapanโ appears only once โ HashSet automatically handles duplicates.
โ๏ธ How It Works Internally
Under the hood, a HashSet uses a HashMap where:
Elements are stored as keys.
A dummy value (usually a static constant) acts as the value.
When you call add(element):
The elementโs hashCode() is computed.
Itโs placed into a bucket based on that hash.
If another element has the same hash (collision), itโs stored in a linked list or tree within that bucket.
The equals() method ensures duplicates are not added.
โ๏ธ Common Methods
| Method | Description |
|---|---|
add(E e) | Adds element if not already present |
remove(Object o) | Removes element |
contains(Object o) | Checks if element exists |
isEmpty() | Returns true if empty |
size() | Returns number of elements |
clear() | Removes all elements |
๐งฎ Time Complexity
| Operation | Average | Worst Case |
|---|---|---|
| add() | O(1) | O(n) |
| remove() | O(1) | O(n) |
| contains() | O(1) | O(n) |
| iteration | O(n) | O(n) |
โก HashSet provides constant-time performance for most operations โ thatโs why itโs widely used for lookups and membership checks.
๐ก Key Features
๐ซ No duplicates โ each element is unique.
โก Fast lookup using hashing.
๐ No guaranteed order โ iteration order may differ from insertion order.
๐ฆ Allows one null element.
โ Not thread-safe โ use Collections.synchronizedSet() for concurrency.
๐ Example: Removing Duplicates from a List
import java.util.*; public class RemoveDuplicates { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5); HashSet<Integer> unique = new HashSet<>(numbers); System.out.println(unique); // [1, 2, 3, 4, 5] } } ๐ This is one of the most common and elegant uses of a HashSet.
๐ Example: Checking Membership Efficiently
HashSet<String> users = new HashSet<>(); users.add("mohammed"); users.add("ahmed"); if (users.contains("mohammed")) { System.out.println("Welcome back!"); } This operation is instant (O(1)) โ much faster than searching a list.
๐งฉ HashSet vs TreeSet vs LinkedHashSet
| Feature | HashSet | LinkedHashSet | TreeSet |
|---|---|---|---|
| Order | No order | Maintains insertion order | Sorted order |
| Speed | Fastest | Slightly slower | Slower (due to sorting) |
| Backed By | HashMap | LinkedHashMap | TreeMap |
| Allows Null | Yes | Yes | No |
| Use Case | Unordered unique items | Preserve insertion order | Sorted unique items |
๐ Real-World Uses of HashSet
- ๐งพ Removing Duplicates
Cleaning up data โ for example, user emails or IDs that appear multiple times.
- ๐ Checking Membership
Efficient โalready exists?โ checks (e.g., registered usernames, cached results).
- ๐ง Tracking Unique Events
Game achievements, visited URLs, or user actions that should happen only once.
- ๐ Efficient Lookup Tables
Fast lookups for values without caring about order โ like tags, keywords, or filters.
โ๏ธ Example: Unique Visitors in a Web App
import java.util.HashSet; public class UniqueVisitors { public static void main(String[] args) { HashSet<String> visitors = new HashSet<>(); visitors.add("user123"); visitors.add("guest456"); visitors.add("user123"); // duplicate System.out.println("Unique visitors: " + visitors.size()); } } โ Output:
Unique visitors: 2
โ ๏ธ Common Mistakes
โ Expecting insertion order โ HashSet does not maintain it.
โ Forgetting to override hashCode() and equals() in custom objects.
โ Using mutable objects as keys โ changing them breaks hash consistency.
๐งฉ Example: Custom Object in HashSet
import java.util.*; class Student { String name; int id; Student(String name, int id) { this.name = name; this.id = id; } @Override public int hashCode() { return Objects.hash(id); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Student)) return false; Student s = (Student) o; return id == s.id; } } public class CustomHashSet { public static void main(String[] args) { HashSet<Student> set = new HashSet<>(); set.add(new Student("Ali", 1)); set.add(new Student("Ali", 1)); // duplicate ignored System.out.println("Total students: " + set.size()); // 1 } } Without overriding hashCode() and equals(), this would incorrectly count as 2 students.
๐ก Final Thought
The HashSet is your go-to structure when you want uniqueness and speed without worrying about order.
Itโs one of the fastest and most memory-efficient collections in Java โ a real workhorse behind the scenes of many high-performance systems. โก
Top comments (0)