🌐
Oracle
docs.oracle.com › en › java › javase › 17 › docs › api › java.base › java › util › HashSet.html
HashSet (Java SE 17 & JDK 17)
April 21, 2026 - This class offers constant time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets. Iterating over this set requires time proportional to the sum of the HashSet instance's size (the number of elements) plus the "capacity" of the backing HashMap instance (the number of buckets).
🌐
GitHub
github.com › openjdk › jdk › blob › master › src › java.base › share › classes › java › util › HashSet.java
jdk/src/java.base/share/classes/java/util/HashSet.java at master · openjdk/jdk
@java.io.Serial · static final long serialVersionUID = -5024744406713321676L; · transient HashMap<E,Object> map; · // Dummy value to associate with an Object in the backing Map · static final Object PRESENT = new Object(); · /** * Constructs a new, empty set; the backing {@code HashMap} instance has · * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<>(); } ·
Author   openjdk
🌐
Oracle
docs.oracle.com › en › java › javase › 21 › docs › api › java.base › java › util › HashSet.html
HashSet (Java SE 21 & JDK 21)
January 20, 2026 - To create a HashSet with an initial capacity that accommodates an expected number of elements, use newHashSet.
🌐
Oracle
docs.oracle.com › en › java › javase › 17 › docs › api › java.base › java › util › class-use › HashSet.html
Uses of Class java.util.HashSet (Java SE 17 & JDK 17)
January 20, 2026 - Package javax.print.attribute.standard contains classes for specific printing attributes. ... Hash table and linked list implementation of the Set interface, with predictable iteration order. Subclasses of HashSet in javax.print.attribute.standard
🌐
Oracle
docs.oracle.com › en › java › javase › 17 › docs › api › java.base › java › util › Set.html
Set (Java SE 17 & JDK 17)
April 21, 2026 - Package java.util · Type Parameters: E - the type of elements maintained by this set · All Superinterfaces: Collection<E>, Iterable<E> All Known Subinterfaces: EventSet, NavigableSet<E>, SortedSet<E> All Known Implementing Classes: AbstractSet, ConcurrentHashMap.KeySetView, ConcurrentSkipListSet, CopyOnWriteArraySet, EnumSet, HashSet, JobStateReasons, LinkedHashSet, TreeSet ·
🌐
Oracle
docs.oracle.com › en › java › javase › 18 › docs › api › java.base › java › util › HashSet.html
HashSet (Java SE 18 & JDK 18)
August 18, 2022 - This class offers constant time performance for the basic operations (add, remove, contains and size), assuming the hash function disperses the elements properly among the buckets. Iterating over this set requires time proportional to the sum of the HashSet instance's size (the number of elements) plus the "capacity" of the backing HashMap instance (the number of buckets).
🌐
Oracle
docs.oracle.com › en › java › javase › 17 › docs › api › java.base › java › util › LinkedHashSet.html
LinkedHashSet (Java SE 17 & JDK 17)
January 20, 2026 - This class provides all of the optional Set operations, and permits null elements. Like HashSet, it provides constant-time performance for the basic operations (add, contains and remove), assuming the hash function disperses elements properly among the buckets.
🌐
GeeksforGeeks
geeksforgeeks.org › java › hashset-in-java
HashSet in Java - GeeksforGeeks
Capacity refers to the number of buckets in the hash table. The default capacity of a HashSet is 16 and the load factor is 0.75.
Published   April 24, 2026
Find elsewhere
🌐
Medium
rameshfadatare.medium.com › java-hashset-691f9c5337de
Java HashSet. Welcome to the Java Collections… | by Ramesh Fadatare | Medium
September 19, 2024 - HashSet in Java is a part of the Java Collections Framework and implements the Set interface. It is a collection that uses a hash table for storage. Unlike List, a Set does not allow duplicate elements.
🌐
CodeSignal
codesignal.com › learn › courses › hashing-dictionaries-and-sets-in-java › lessons › mastering-java-hashset-an-in-depth-exploration-of-implementation-and-complexity-analysis
Mastering Java HashSet: An In-depth Exploration of ...
Under its hood, a HashSet uses a hash table to manage all its elements. A hash table revolves around an array of buckets that store all items. A hash function is integrated to generate a hash code; the hashed key indicates the memory location where each element gets stored, accelerating the element storage and retrieval process. In Java, the add(), remove(), and contains() operations in the HashSet class rely on the hash code of the object you're dealing with.
🌐
Android Developers
developer.android.com › api reference › hashset
HashSet | API reference | Android Developers
Skip to main content · English · Deutsch · Español – América Latina · Français · Indonesia · Polski · Português – Brasil · Tiếng Việt · 中文 – 简体
Top answer
1 of 2
8

Don’t know, don’t care

The concrete class used by Set.of (and List.of, Map.of) is not documented. All we know is that the object returned (a) implements the interface, and (b) is unmodifiable.

That is all we need to know. We should not care about the particular concrete class used under the covers.

Being of unknown concrete class gives freedom to the implementors of the of methods.

  • Those programmers are free to optimize according to the nature of your arguments. For example, if you are passing enum arguments, the highly optimized EnumSet class might be used behind the scenes.
  • Those programmers are free to change their concrete class between versions of Java. For example, Java 17 implementation might return one concrete class while Java 18 returns another.

So you should never depend on a particular concrete class being utilized by the of/copyOf methods.

You asked:

What is the real difference between those two?

In your first one, we know the concrete class. And the resulting set is modifiable.

In your second one, we do not know the concrete class, nor do we care about the concrete class. And the resulting set is unmodifiable.

Code Concrete Class Modifiable
new HashSet<>() {{ add("a"); add("b"); add("c"); }} known modifiable
Set.of( "a", "b", "c" unknown unmodifiable

Avoid double-brace

As others said, it’s generally best to avoid double-brace initialization.

If you want the convenience of compact literals-style initialization of your modifiable collection, combine with the of methods. You can pass an existing collection to the constructor.

Set< String > set =
    new HashSet<>(
        Set.of( "a", "b", "c" )  // Pass a collection to constructor. 
    )
;

“But I do care …”

If you do care about the specific details of the implementation, then you should not use Set.of. The implementation details may vary as discussed above, so you should not rely on a specific implementation with Set.of.

When your project has specific needs, you should explicitly choose a particular implementation that meets those needs. You can choose one of the bundled implementations, obtain one from a third-party library such as Eclipse Collections or Google Guava, or write your own.

Tip: You can leverage the convenient syntax of Set.of by passing its result to the constructor of your chosen implementation. See the code example above:

new HashSet<>( Set.of( … ) )  // Populate new `HashSet` with elements of the unmodifiable `Set` returned from `Set.of`. 
2 of 2
2

The implementation class resulting from Set.of(...) is not guaranteed. It could change depending on the runtime implementation or in future versions. However, some of its characteristics—chiefly immutability—are guaranteed.

When you use "double-brace initialization", you are defining a new anonymous class that derives from the specified type. So MySillyTest$1 extends HashSet because that's what you specified. Note that double-brace initialization has problems; I don't allow it, and I discourage others from using it.

The important difference between the two is the immutability resulting from Set.of(...). If you need a mutable set, it's not an option. But if you can use an immutable set, it provides superior readability and performance.

Even if you need a mutable set, however, don't look at double-brace initialization as an alternative to Set.of(...); just use a HashSet in the conventional way.

🌐
Upgrad
upgrad.com › home › tutorials › software & tech › hashset in java
HashSet in Java - A Complete Guide | upGrad
March 4, 2025 - The HashSet class implements the Set interface, it uses hashtable to store the elements and contains only unique elements.