liveBook · Manning

Set

As explained in 100 Java Mistakes and How to Avoid Them

A set is a collection abstraction that stores distinct elements without duplicate membership.

A set stores distinct elements, but safe use depends on how membership and equality are implemented. Set implementations are specified to compare contents with equals(), unlike queues and other collection types for which content equality is not generally required. A List and a Set are never equal by specification, even when they contain the same elements. section 7.2

Preserve the equality contract when wrapping sets. Collections.unmodifiableCollection(set) does not itself implement Set, so it cannot delegate set-style equality without risking asymmetric results. Use Collections.unmodifiableSet() when callers need an unmodifiable set that still compares by contents as a set. section 7.2

Do not assume every Set handles null searches alike. HashSet can contain null, while factory-created sets such as Set.of() reject null elements and also reject contains(null). The declared Set type does not reveal that difference, so replacing a legacy unmodifiable set with Set.of() can turn a previously harmless lookup into a NullPointerException. section 8.3

Guard a nullable lookup

When the searched value may be null, make that case explicit: obj != null && platforms.contains(obj) This avoids calling contains(null) on a null-hostile set. Do not blindly modernize older unmodifiable set declarations to Set.of() unless callers and tests establish that null is never searched for. section 8.3

Treat objects stored in a hash-based set as stable with respect to equals() and hashCode(). If a mutable element changes after insertion, its hash code may change while it remains in the bucket selected by its old hash code. A later contains() or remove() lookup uses the new hash code, searches a different bucket, and may fail to find the same object. section 8.6

Set<List<String>> set = new HashSet<>();
List<String> list = new ArrayList<>();
set.add(list);
list.add("Value");
System.out.println(set.contains(list));    #1

The list is inserted while empty, then mutated. Its changed content changes its hash code, so contains(list) can search the wrong HashSet bucket and report false. section 8.6

Avoid membership failures by following these rules:

  • Do not mutate an object after using it as a HashSet element when mutation can affect equals() or hashCode(). section 8.6
  • Prefer immutable alternatives for date-and-time values when possible; mutable java.util.Date and Calendar can be changed after insertion. section 8.6
  • Be especially cautious with StringBuilder: its content-based compareTo() conflicts with identity-based equals() and hashCode(), making modified HashSet elements unreliable. section 8.6
  • Check nullable search inputs before calling contains() on sets whose implementation may be hidden behind the Set interface. section 8.3

Static analysis can report some suspicious equals() uses, but it cannot make collection equality or mutation safe automatically. Verify the concrete collection behavior, equality semantics, and whether stored objects can change after insertion. section 7.2 section 8.6

How 100 Java Mistakes and How to Avoid Them covers it

How deep it goes
Explains equality contracts, null dispositions, and hash-bucket lookup consequences through focused failure cases.
Examples
Demonstrates Set.of() migration and a mutated List<String> that HashSet can no longer find.
What it assumes
Assumes Java collection interfaces and object equality, then elaborates their set-specific failure modes.
What you can do after
Diagnose/debug with it by guarding null lookups and identifying mutated hash-based set elements.
How it connects
Connects sets with equals(), hashCode(), HashSet, collection factories, null, and immutability.

Also explained in

Compare how 15 books explain set →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Java Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.