I wanted to ask - what is the difference between
Set<CurrencyType> set1 = new HashSet<>() {{
add("a");
add("b");
add("c");
}}
and
Set<CurrencyType> set2 = Set.of(
"a",
"b",
"c"
)
In debug mode in a @Test named MySillyTest
(this name will come back very soon) i can see that set1
is an instance of MySillyTest$1
, but I assume it is just a HashSet
. set2
on the other hand is an instance of ImmutableCollections$SetN
. What is the real difference between those two? What implementation of java.util.Set
is Set.of()
using? Is there a performance/memory usage/cpu usage difference between those two?
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.
EnumSet
class might be used behind the scenes. 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 |
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.
)
;
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.