Implementations of Set interface
Let’s provide a brief explanation of each Set implementation along with an example demonstrating its usage.

Table of Contents
- 1. HashSet:
- HashSet is implemented using a hash table data structure, providing constant-time performance for basic operations like add, remove, and contains.
- It does not guarantee the order of elements.
- Suitable for general-purpose use cases where fast lookup is important, and the order of elements is not significant.
Example Usage of Sets
```java
import java.util.HashSet;
import java.util.Set;
public class HashSetExample {
public static void main(String[] args) {
// Creating a HashSet
Set<String> hashSet = new HashSet<>();
// Adding elements
hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Cherry");
// Printing the HashSet
System.out.println("HashSet: " + hashSet);
// Checking for an element
System.out.println("Contains 'Banana'? " + hashSet.contains("Banana"));
// Removing an element
hashSet.remove("Cherry");
System.out.println("HashSet after removing 'Cherry': " + hashSet);
}
}
```
- 2. TreeSet:
- TreeSet is implemented using a red-black tree data structure, maintaining elements in sorted order.
- It offers guaranteed log(n) time complexity for basic operations like add, remove, and contains.
- Suitable for scenarios where elements need to be maintained in sorted order.
Example Usage of Sets
```java
import java.util.Set;
import java.util.TreeSet;
public class TreeSetExample {
public static void main(String[] args) {
// Creating a TreeSet
Set<Integer> treeSet = new TreeSet<>();
// Adding elements
treeSet.add(5);
treeSet.add(2);
treeSet.add(8);
// Printing the TreeSet
System.out.println("TreeSet: " + treeSet);
}
}
```
- 3. LinkedHashSet:
- LinkedHashSet maintains elements in insertion order, combining the features of HashSet and LinkedList.
- It provides constant-time performance for add, remove, and contains operations.
- Suitable for scenarios where iteration order is important.
Example Usage of Sets
```java
import java.util.LinkedHashSet;
import java.util.Set;
public class LinkedHashSetExample {
public static void main(String[] args) {
// Creating a LinkedHashSet
Set<String> linkedHashSet = new LinkedHashSet<>();
// Adding elements
linkedHashSet.add("Apple");
linkedHashSet.add("Banana");
linkedHashSet.add("Cherry");
// Printing the LinkedHashSet
System.out.println("LinkedHashSet: " + linkedHashSet);
}
}
```
- 4. EnumSet:
- EnumSet is specifically designed for use with enum types, representing a set of enum constants efficiently using bit vectors.
- It offers constant-time performance for the basic operations and is highly memory efficient.
Example Usage of Sets
```java
import java.util.EnumSet;
public class EnumSetExample {
enum Days { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
public static void main(String[] args) {
// Creating an EnumSet
EnumSet<Days> daysEnumSet = EnumSet.of(Days.MONDAY, Days.TUESDAY, Days.WEDNESDAY);
// Printing the EnumSet
System.out.println("Days EnumSet: " + daysEnumSet);
}
}
```
- 5. CopyOnWriteArraySet:
- CopyOnWriteArraySet provides thread-safety for concurrent access without the need for external synchronization.
- It guarantees immutability and consistency for readers while allowing writers to operate on a separate copy of the underlying array.
Example Usage of Sets
```java
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public class CopyOnWriteArraySetExample {
public static void main(String[] args) {
// Creating a CopyOnWriteArraySet
Set<String> copyOnWriteArraySet = new CopyOnWriteArraySet<>();
// Adding elements
copyOnWriteArraySet.add("Apple");
copyOnWriteArraySet.add("Banana");
copyOnWriteArraySet.add("Cherry");
// Printing the CopyOnWriteArraySet
System.out.println("CopyOnWriteArraySet: " + copyOnWriteArraySet);
}
}
```
These examples demonstrate the usage of various Set implementations with different characteristics, allowing developers to choose the most suitable one based on their requirements.