The Set Interface in Java
The Set interface is part of the Java Collections Framework and represents a collection of unique elements. Unlike a List, a Set does not allow duplicate values.
The Set interface extends the Collection interface.
Key Characteristics
- Stores only unique elements.
- Does not allow duplicate values.
- Part of the Java Collections Framework.
- Useful when uniqueness is required.
Implementations of the Set Interface
Java provides several implementations of the Set interface.
HashSet
A HashSet stores elements using a hash table.
Features
- Does not maintain insertion order.
- Allows one
nullelement. - Provides fast lookup, insertion, and deletion.
- Average time complexity for
add(),remove(), andcontains()is O(1).
Best Use Cases
- Removing duplicate values.
- Fast searching.
- When ordering is not important.
LinkedHashSet
LinkedHashSet extends HashSet by maintaining a doubly linked list of elements.
Features
- Preserves insertion order.
- Allows one
nullelement. - Slightly slower than
HashSetbecause of the linked list.
Best Use Cases
- When uniqueness and insertion order are both required.
TreeSet
TreeSet implements the NavigableSet interface.
Features
- Stores elements in sorted (ascending) order.
- Does not allow
nullvalues. - Uses a Red-Black Tree internally.
- Basic operations take O(log n) time.
Best Use Cases
- Maintaining sorted data.
- Range-based operations.
- Automatically sorting elements.
HashSet vs LinkedHashSet vs TreeSet
| Feature | HashSet | LinkedHashSet | TreeSet |
|---|---|---|---|
| Duplicate elements | ❌ Not allowed | ❌ Not allowed | ❌ Not allowed |
| Order maintained | No | Insertion order | Sorted order |
| Internal structure | Hash table | Hash table + Linked List | Red-Black Tree |
| Performance | O(1) | O(1) | O(log n) |
| Allows null | Yes (one) | Yes (one) | No |
Real-Life Example
Think of a classroom attendance register.
Each student's name should appear only once.
A Set ensures that duplicate names cannot be added.
Real-Time Testing Example
In Selenium automation, a Set is commonly used to store:
- Browser window handles
- Unique URLs
- Test IDs
Example:
Set<String> windows = driver.getWindowHandles();
Since every browser window has a unique handle, a Set is the ideal collection.
How HashMap Works Internally
HashMap is one of the most commonly used implementations of the Map interface.
It stores data as key-value pairs.
Internal Data Structure
Internally, a HashMap uses an array of buckets.
Each bucket stores one or more entries.
Each entry contains:
- Key
- Value
- Hash value
- Reference to the next node (if collision occurs)
Hashing
When a key-value pair is inserted:
- Java calls the key's
hashCode()method. - The hash code determines the bucket index.
- The entry is stored in that bucket.
Collision Handling
Sometimes two keys produce the same bucket index.
This is called a collision.
HashMap handles collisions using:
- Linked List (before Java 8)
- Balanced Tree (Red-Black Tree) (Java 8 and later, after a threshold)
This improves performance when many collisions occur.
Dynamic Resizing
As more elements are added:
- HashMap automatically increases its capacity.
- Existing entries are rehashed into the new bucket array.
This resizing is controlled by the load factor.
Performance
| Operation | Average Time Complexity |
|---|---|
| put() | O(1) |
| get() | O(1) |
| remove() | O(1) |
| Worst case | O(n) |
NULL Values
A HashMap allows:
- One
nullkey. - Multiple
nullvalues.
Example
import java.util.HashMap;
public class Example {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.put("banana", 20);
map.put("cherry", 30);
System.out.println(map.get("apple"));
}
}
Output
10
ArrayList vs LinkedList
Both classes implement the List interface, but they use different internal data structures.
ArrayList
ArrayList stores elements in a dynamic array.
Advantages
- Fast random access.
- Less memory usage.
- Best for read-heavy applications.
LinkedList
LinkedList stores elements as doubly linked nodes.
Advantages
- Fast insertion and deletion.
- Efficient when elements are frequently added or removed.
ArrayList vs LinkedList Comparison
| Feature | ArrayList | LinkedList |
|---|---|---|
| Internal structure | Dynamic array | Doubly linked list |
| Random access | O(1) | O(n) |
| Insertion/Deletion | O(n) | O(1) (at ends or with reference) |
| Memory usage | Lower | Higher |
| Best for | Frequent reading | Frequent insertion/deletion |
Real-Life Example
ArrayList
Like books on a bookshelf.
You can directly pick any book by its position.
LinkedList
Like train coaches.
Adding or removing coaches is easy, but reaching a specific coach takes time.
Real-Time Testing Example
ArrayList
Used for storing:
- Usernames
- Passwords
- Test data
- Static configuration
LinkedList
Used for storing:
- Execution logs
- Retry steps
- Undo history
- Dynamic execution sequences
How to Make a Map Synchronized
By default, HashMap is not thread-safe.
You can make it synchronized using Collections.synchronizedMap().
Example
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class Example {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
Map<String, Integer> synchronizedMap =
Collections.synchronizedMap(map);
}
}
The returned map is thread-safe.
Important Note
When iterating over a synchronized map, you must explicitly synchronize on the map.
synchronized (synchronizedMap) {
for (Map.Entry<String, Integer> entry :
synchronizedMap.entrySet()) {
System.out.println(entry);
}
}
This prevents ConcurrentModificationException.
Real-Life Example
Imagine several people writing in a shared diary.
Only one person can write at a time to prevent overwriting each other's work.
Real-Time Testing Example
In Selenium automation frameworks, synchronized maps are often used to store:
- Environment configuration
- Parallel execution results
- Shared test data
This ensures multiple threads can safely access shared data.
Collections.synchronizedMap() vs ConcurrentHashMap
Both provide thread safety but work differently.
| Feature | Collections.synchronizedMap() | ConcurrentHashMap |
|---|---|---|
| Thread-safe | Yes | Yes |
| Locking | Entire map | Individual buckets/segments |
| Concurrency | One thread at a time | Multiple threads simultaneously |
| Performance | Lower | Higher |
Real-Life Example
synchronizedMap
Only one person can use the shared diary at a time.
ConcurrentHashMap
Multiple people can write in different sections simultaneously.
Which One Should You Use?
- Use Collections.synchronizedMap() when synchronization requirements are simple.
- Use ConcurrentHashMap for high-performance multithreaded applications.
forEach vs Iterator
Both are used for traversing collections.
forEach
Introduced in Java 8.
Uses lambda expressions for concise iteration.
Example
list.forEach(item -> System.out.println(item));
Advantages
- Simple.
- Readable.
- Less code.
Limitation
Cannot safely remove elements while iterating.
Iterator
Available since Java 1.2.
Uses:
hasNext()next()
Example
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
Advantages
- Can safely remove elements using
iterator.remove(). - More control over iteration.
forEach vs Iterator Comparison
| Feature | forEach | Iterator |
|---|---|---|
| Introduced | Java 8 | Java 1.2 |
| Syntax | Lambda expression | hasNext() and next() |
| Remove elements | ❌ No | ✅ Yes |
| Readability | Cleaner | More verbose |
Real-Life Example
forEach
A teacher gives instructions to every student at once.
Iterator
A teacher checks each student individually and removes absent students from the attendance list.
Real-Time Testing Example
forEach
Useful for:
- Printing test results.
- Logging execution details.
Iterator
Useful for:
- Removing failed test cases.
- Filtering test data while iterating.
FAQs
1. What Is the Set Interface Used For?
The Set interface stores unique elements and does not allow duplicates.
Common implementations include:
HashSetLinkedHashSetTreeSet
2. How Does a HashMap Work Internally?
A HashMap stores key-value pairs in an array of buckets.
- The key's
hashCode()determines the bucket. - Collisions are handled using a linked list or a balanced tree (Java 8+).
- It automatically resizes based on the load factor.
- It allows one
nullkey and multiplenullvalues.
3. What Is the Difference Between ArrayList and LinkedList?
- ArrayList uses a dynamic array and provides fast random access.
- LinkedList uses doubly linked nodes and provides faster insertion and deletion.
4. How Do You Make a Map Synchronized?
Wrap the map using Collections.synchronizedMap().
While iterating, synchronize on the map inside a synchronized block to avoid ConcurrentModificationException.
5. What Is the Difference Between Collections.synchronizedMap() and ConcurrentHashMap?
Collections.synchronizedMap()locks the entire map, allowing only one thread at a time.ConcurrentHashMaplocks only portions of the map, allowing multiple threads to work concurrently with better performance.
6. What Is the Difference Between forEach and Iterator?
- forEach (Java 8) uses lambda expressions and is concise but cannot remove elements during iteration.
- Iterator (Java 1.2) provides explicit control over iteration and supports safe element removal using
iterator.remove().