Set / HashSet
java.util.Set is the collection of unique values. HashSet is the workhorse (O(1) ops), LinkedHashSet preserves insertion order, TreeSet maintains sorted order with O(log n), and the immutable Set.of(...) gives you compact literals. Use Set whenever the question is "does this contain X?" or "what are the unique items?".
HashSet, LinkedHashSet, TreeSet, and Set.of()
EXAMPLE
import java.util.*;
import java.util.stream.*;
public class SetsDemo {
public static void main(String[] args) {
// 1) HashSet — no ordering, fastest membership tests
Set<String> tags = new HashSet<>(List.of("alpha", "beta", "alpha", "gamma"));
System.out.println(tags); // {alpha, beta, gamma} (order arbitrary)
System.out.println(tags.contains("beta")); // true
System.out.println(tags.size()); // 3
// 2) Immutable Set.of — Java 9+, compact and safe
Set<String> roles = Set.of("admin", "editor", "viewer");
// roles.add("ghost"); // throws UnsupportedOperationException
// 3) LinkedHashSet — preserves insertion order (handy for stable iteration)
Set<String> insertionOrdered = new LinkedHashSet<>();
insertionOrdered.add("c"); insertionOrdered.add("a"); insertionOrdered.add("b");
System.out.println(insertionOrdered); // [c, a, b]
// 4) TreeSet — sorted, O(log n), range queries
TreeSet<Integer> sorted = new TreeSet<>(List.of(5, 1, 9, 3, 7));
System.out.println(sorted); // [1, 3, 5, 7, 9]
System.out.println(sorted.first() + ".." + sorted.last()); // 1..9
System.out.println(sorted.subSet(3, 8)); // [3, 5, 7]
System.out.println(sorted.higher(5)); // 7
// 5) Custom comparator — order by length then alphabetically
TreeSet<String> byLen = new TreeSet<>(
Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder())
);
byLen.addAll(List.of("bear", "ant", "cat", "ape"));
System.out.println(byLen); // [ant, ape, cat, bear]
// 6) EnumSet — extremely fast for enum keys (bitmask under the hood)
enum Permission { READ, WRITE, EXECUTE }
EnumSet<Permission> perms = EnumSet.of(Permission.READ, Permission.WRITE);
System.out.println(perms.contains(Permission.EXECUTE)); // false
// 7) Set operations — union, intersection, difference
Set<Integer> a = new HashSet<>(List.of(1, 2, 3, 4));
Set<Integer> b = new HashSet<>(List.of(3, 4, 5, 6));
Set<Integer> union = new HashSet<>(a); union.addAll(b);
Set<Integer> intersection = new HashSet<>(a); intersection.retainAll(b);
Set<Integer> difference = new HashSet<>(a); difference.removeAll(b);
System.out.println(union); // [1, 2, 3, 4, 5, 6]
System.out.println(intersection); // [3, 4]
System.out.println(difference); // [1, 2]
// 8) Streams + collectors
List<String> words = List.of("ant", "bee", "ant", "cat", "bee");
Set<String> unique = words.stream().collect(Collectors.toSet());
// 9) Concurrent: use ConcurrentHashMap.newKeySet() or
// Collections.newSetFromMap(new ConcurrentHashMap<>())
Set<String> shared = ConcurrentHashMap.<String>newKeySet();
shared.add("x"); shared.add("y");
// 10) Watch out: equals + hashCode MUST be consistent for elements
// A class that returns a different hashCode after the object is added
// becomes unfindable — common bug with mutable element types.
}
}
Why it matters
Use Set.of() for read-only constants and EnumSet for sets of enum values — both are dramatically more efficient than the equivalent HashSet, and the immutability makes them safe to share across threads. Reach for HashSet only when you genuinely need to mutate.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
Set<String> tags = new HashSet<>(List.of("red","blue","red"));
System.out.println(tags); // [red, blue]
Try it Yourself »
Discussion
Loading…