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.

Advertisement

HashSet

A HashSet stores elements using a hash table.

Features

  • Does not maintain insertion order.
  • Allows one null element.
  • Provides fast lookup, insertion, and deletion.
  • Average time complexity for add(), remove(), and contains() 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 null element.
  • Slightly slower than HashSet because 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 null values.
  • 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:

  1. Java calls the key's hashCode() method.
  2. The hash code determines the bucket index.
  3. 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 null key.
  • Multiple null values.

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:

  • HashSet
  • LinkedHashSet
  • TreeSet

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 null key and multiple null values.

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.
  • ConcurrentHashMap locks 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().