Skip to content
Dev Dump

🌿 Java Set Interface - Complete Guide

β€œSets provide efficient collections of unique elements, perfect for membership testing, duplicate removal, and mathematical set operations.”

The Set interface represents a collection that contains no duplicate elements. It models the mathematical set abstraction and provides operations for union, intersection, and difference. Sets are primarily used for membership testing and eliminating duplicates.

set

FeatureDescriptionExample
Unique ElementsNo duplicates allowed{a, b, c} not {a, b, a}
Mathematical OperationsUnion, intersection, difference{a,b} βˆͺ {b,c} = {a,b,c}
Membership TestingFast contains() operationset.contains(x)
At Most One NullMaximum one null element{null, a, b} is valid
Collection<E>
└── Set<E> (interface)
β”œβ”€β”€ HashSet<E> - Hash table implementation, O(1) operations
β”œβ”€β”€ LinkedHashSet<E> - Maintains insertion order
β”œβ”€β”€ SortedSet<E> (interface)
β”‚ └── NavigableSet<E> (interface)
β”‚ └── TreeSet<E> - Red-black tree, sorted elements
β”œβ”€β”€ EnumSet<E> - Specialized for enum types
└── CopyOnWriteArraySet<E> - Thread-safe, read-optimized
ImplementationAddRemoveContainsIterationMemoryThread SafeOrderingNull Support
HashSetO(1)*O(1)*O(1)*O(n)Medium❌Noβœ… One null
LinkedHashSetO(1)*O(1)*O(1)*O(n)High❌Insertionβœ… One null
TreeSetO(log n)O(log n)O(log n)O(n)Medium❌Sorted❌ No nulls
EnumSetO(1)O(1)O(1)O(n)Very Low❌Declaration❌ No nulls
CopyOnWriteArraySetO(n)O(n)O(n)O(n)Highβœ…Insertionβœ… Nulls OK

* Average case - worst case O(n) due to hash collisions

public interface Set<E> extends Collection<E> {
// Basic operations (inherited from Collection)
boolean add(E e); // Returns false if already present
boolean remove(Object o);
boolean contains(Object o);
int size();
boolean isEmpty();
Iterator<E> iterator();
// Bulk operations
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c); // Union
boolean retainAll(Collection<?> c); // Intersection
boolean removeAll(Collection<?> c); // Difference
void clear();
// Array conversion
Object[] toArray();
<T> T[] toArray(T[] a);
// Java 8+ additions (inherited from Collection)
default boolean removeIf(Predicate<? super E> filter);
default Stream<E> stream();
default Stream<E> parallelStream();
}
public class SetMathematicalOperations {
public void demonstrateSetOperations() {
Set<String> set1 = new HashSet<>(Arrays.asList("a", "b", "c", "d"));
Set<String> set2 = new HashSet<>(Arrays.asList("c", "d", "e", "f"));
// Union (A βˆͺ B) - all elements from both sets
Set<String> union = new HashSet<>(set1);
union.addAll(set2);
System.out.println("Union: " + union); // [a, b, c, d, e, f]
// Intersection (A ∩ B) - common elements
Set<String> intersection = new HashSet<>(set1);
intersection.retainAll(set2);
System.out.println("Intersection: " + intersection); // [c, d]
// Difference (A - B) - elements in A but not in B
Set<String> difference = new HashSet<>(set1);
difference.removeAll(set2);
System.out.println("Difference: " + difference); // [a, b]
// Symmetric difference (A β–³ B) - elements in either A or B but not both
Set<String> symmetricDiff = new HashSet<>(union);
symmetricDiff.removeAll(intersection);
System.out.println("Symmetric Difference: " + symmetricDiff); // [a, b, e, f]
// Subset check
boolean isSubset = set1.containsAll(intersection); // true
System.out.println("Intersection is subset of set1: " + isSubset);
}
}

HashSet is a hash table-based implementation of the Set interface that provides:

  • O(1) average case operations for add, remove, and contains
  • No ordering guarantees
  • Efficient memory usage
  • Fast membership testing
public class HashSetConstructionExamples {
public void demonstrateConstruction() {
// Default constructor (initial capacity 16, load factor 0.75)
HashSet<String> set1 = new HashSet<>();
// With initial capacity
HashSet<String> set2 = new HashSet<>(100);
// With initial capacity and load factor
HashSet<String> set3 = new HashSet<>(100, 0.8f);
// From existing collection
List<String> existing = Arrays.asList("a", "b", "c");
HashSet<String> set4 = new HashSet<>(existing);
// Using factory methods (Java 9+)
Set<String> immutableSet = Set.of("x", "y", "z");
HashSet<String> mutableSet = new HashSet<>(immutableSet);
}
}
public class HashSetPerformanceExample {
public void demonstratePerformance() {
HashSet<String> names = new HashSet<>();
// Fast insertion (O(1) average)
names.add("Alice");
names.add("Bob");
names.add("Charlie");
names.add("David");
// Fast membership testing (O(1) average)
boolean hasAlice = names.contains("Alice"); // true
boolean hasEve = names.contains("Eve"); // false
// Fast removal (O(1) average)
boolean removed = names.remove("Bob");
// Duplicate elements are ignored
boolean added = names.add("Alice"); // false - already exists
System.out.println("Size after duplicate add: " + names.size()); // Still 3
// Bulk operations
Set<String> moreNames = Set.of("Eve", "Frank", "Grace");
names.addAll(moreNames);
// Iteration (order not guaranteed)
for (String name : names) {
System.out.println("Name: " + name);
}
}
}

LinkedHashSet extends HashSet to maintain a doubly-linked list that preserves:

  • Insertion order of elements
  • HashSet performance characteristics
  • Predictable iteration order
  • Higher memory overhead than HashSet
public class LinkedHashSetExamples {
public void demonstrateLinkedHashSet() {
LinkedHashSet<String> orderedSet = new LinkedHashSet<>();
// Add elements in specific order
orderedSet.add("first");
orderedSet.add("second");
orderedSet.add("third");
orderedSet.add("fourth");
// Iteration preserves insertion order
System.out.println("Insertion order preserved:");
for (String item : orderedSet) {
System.out.print(item + " "); // first second third fourth
}
System.out.println();
// Remove and re-add (maintains order)
orderedSet.remove("second");
orderedSet.add("second");
System.out.println("After remove and re-add:");
for (String item : orderedSet) {
System.out.print(item + " "); // first third fourth second
}
System.out.println();
// From existing collection
List<String> list = Arrays.asList("zebra", "apple", "banana");
LinkedHashSet<String> fromList = new LinkedHashSet<>(list);
System.out.println("From list (preserves list order):");
for (String item : fromList) {
System.out.print(item + " "); // zebra apple banana
}
System.out.println();
}
}

TreeSet is a red-black tree-based implementation that provides:

  • Sorted elements in natural order or custom comparator
  • O(log n) operations for add, remove, and contains
  • Navigable operations (ceiling, floor, higher, lower)
  • No null elements allowed
public class TreeSetConstructionExamples {
public void demonstrateConstruction() {
// Default constructor (natural ordering)
TreeSet<Integer> numbers = new TreeSet<>();
// With custom comparator
TreeSet<String> reverseOrder = new TreeSet<>(Comparator.reverseOrder());
// With initial collection
List<Integer> existing = Arrays.asList(5, 2, 8, 1, 9);
TreeSet<Integer> fromList = new TreeSet<>(existing);
// Custom object with natural ordering
TreeSet<Person> people = new TreeSet<>();
// Using NavigableSet methods
NavigableSet<Integer> navigableSet = new TreeSet<>();
}
}
public class TreeSetPerformanceExample {
public void demonstratePerformance() {
TreeSet<Integer> sortedSet = new TreeSet<>();
// Insertion (O(log n))
sortedSet.add(5);
sortedSet.add(2);
sortedSet.add(8);
sortedSet.add(1);
sortedSet.add(9);
// Elements are automatically sorted
System.out.println("Sorted elements:");
for (Integer num : sortedSet) {
System.out.print(num + " "); // 1 2 5 8 9
}
System.out.println();
// Navigable operations
Integer ceiling = sortedSet.ceiling(6); // 8 (smallest >= 6)
Integer floor = sortedSet.floor(6); // 5 (largest <= 6)
Integer higher = sortedSet.higher(5); // 8 (smallest > 5)
Integer lower = sortedSet.lower(5); // 2 (largest < 5)
System.out.println("Ceiling(6): " + ceiling);
System.out.println("Floor(6): " + floor);
System.out.println("Higher(5): " + higher);
System.out.println("Lower(5): " + lower);
// Subset operations
NavigableSet<Integer> subset = sortedSet.subSet(2, true, 8, true);
System.out.println("Subset [2,8]: " + subset); // [2, 5, 8]
// Head and tail sets
SortedSet<Integer> headSet = sortedSet.headSet(5);
SortedSet<Integer> tailSet = sortedSet.tailSet(5);
System.out.println("Head set < 5: " + headSet); // [1, 2]
System.out.println("Tail set >= 5: " + tailSet); // [5, 8, 9]
}
}
Use CaseHashSetLinkedHashSetTreeSetEnumSetCopyOnWriteArraySet
General Purposeβœ… Bestβœ… Good⚠️ Good❌ Wrong⚠️ Good
Performanceβœ… Bestβœ… Good⚠️ Goodβœ… Best❌ Poor
Memory Efficiencyβœ… Best❌ Poorβœ… Goodβœ… Best❌ Poor
Ordering❌ Noβœ… Insertionβœ… Sortedβœ… Declarationβœ… Insertion
Thread Safety❌ No❌ No❌ No❌ Noβœ… Best
Range Queries❌ Poor❌ Poorβœ… Best❌ Poor❌ Poor