Java ProgramsCollectionsImmutable Set

Immutable Set in Java

beginner·  Collections  ·  Immutability

Problem

Set.of() (Java 9+) builds a Set that can never be modified after creation, the same immutability guarantee List.of() provides for lists.

Create a Set of elements that can never be added to or removed from after it's built.

Input
Set.of("Apple", "Banana", "Cherry")
Output
Contains Banana: true

Java Program

Java
import java.util.Set; public class ImmutableSetDemo { public static void main(String[] args) { Set<String> fruits = Set.of("Apple", "Banana", "Cherry"); System.out.println("Contains Banana: " + fruits.contains("Banana")); // Set.of("Apple", "Apple") would throw IllegalArgumentException — duplicates aren't allowed } }

Output

Contains Banana: true

Core Logic

Building the set through the Set.of() factory method returns an immutable implementation, the same idea as List.of() but for sets.

How It Works
  1. 1Set.of("Apple", "Banana", "Cherry") returns a Set already populated with those three elements.
  2. 2Reading from it — contains(), iteration, size — works exactly like any other Set.
  3. 3Calling a mutating method like .add(...) on it throws UnsupportedOperationException, the same as List.of().
  4. 4Set.of() does not iterate elements in insertion order — the order elements print in isn't guaranteed, unlike List.of(), which does preserve the order given.
Set.of("Apple", "Banana", "Cherry").contains("Banana") returns true, read like any normal Set.
💡

Key Point: Set.of() rejects duplicate arguments outright — passing the same element twice throws IllegalArgumentException at the moment the set is built, rather than silently keeping just one copy the way a mutable HashSet's add() would.

Complexity
Time Complexity: O(n)Space Complexity: O(n)

Why: Set.of() stores each of the n given elements once, after checking for duplicates among them.

Key Concepts

Set.of()immutabilityduplicate rejection

Approach 2: Java 8

Java
import java.util.Set; import java.util.stream.Collectors; public class ImmutableSetStream { public static void main(String[] args) { Set<String> source = Set.of("Apple", "Banana", "Cherry"); // Transforms each element, then collects the result into a genuinely immutable set Set<String> upper = source.stream() .map(String::toUpperCase) .collect(Collectors.toUnmodifiableSet()); System.out.println("Contains BANANA: " + upper.contains("BANANA")); // upper.add("DATE") here would throw UnsupportedOperationException } }

Output

Contains BANANA: true

Core Logic

Collectors.toUnmodifiableSet() builds an immutable set from a stream pipeline directly, for the common case where the elements are derived from existing data rather than being known ahead of time as literals.

How It Works
  1. 1source.stream() opens a stream over an existing mutable set.
  2. 2.map(String::toUpperCase) transforms each element — something Set.of() can't express, since it just takes fixed elements directly.
  3. 3.collect(Collectors.toUnmodifiableSet()) gathers the transformed elements into a genuinely immutable set, the same UnsupportedOperationException-on-mutation guarantee Set.of() provides.
  4. 4Calling .add(...) on the result throws exactly as it would on a Set.of() result.
Upper-casing {Apple, Banana, Cherry} and collecting produces the immutable set {APPLE, BANANA, CHERRY}, so contains("BANANA") returns true.
💡

Key Point: Set.of() is for elements already known as literals; Collectors.toUnmodifiableSet() is for the more common real-world case — an immutable set built from data that was transformed or derived from another collection first.

Complexity
Time Complexity: O(n)Space Complexity: O(n)

Why: map() visits each of the n source elements once, and collect() builds a new immutable set to hold the transformed elements.

Key Concepts

StreamCollectors.toUnmodifiableSet()

Related Programs