简体   繁体   English

Set.of(E... elements) - 它使用的是哪个 Set 实现? 它与 new HashSet<>() 有什么关系?

[英]Set.of(E... elements) - which Set implementation is it using? and what is its relation to new HashSet<>()?

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 .在名为MySillyTest的 @Test 的调试模式下(这个名称很快就会恢复)我可以看到set1MySillyTest$1的一个实例,但我认为它只是一个HashSet set2 on the other hand is an instance of ImmutableCollections$SetN .另一方面, set2ImmutableCollections$SetN的一个实例。 What is the real difference between those two?这两者之间的真正区别是什么? What implementation of java.util.Set is Set.of() using? Set.of()使用的是java.util.Set的什么实现? Is there a performance/memory usage/cpu usage difference between those two?这两者之间是否存在性能/内存使用/cpu 使用差异?

Don't know, don't care不知道,不关心

The concrete class used by Set.of (and List.of , Map.of ) is not documented. Set.of (和List.ofMap.of )使用的具体 class 没有记录。 All we know is that the object returned (a) implements the interface, and (b) is unmodifiable.我们所知道的是返回的 object (a) 实现了接口,并且 (b) 是不可修改的。

That is all we need to know.这就是我们需要知道的全部。 We should not care about the particular concrete class used under the covers.我们不应该关心幕后使用的特定具体 class。

Being of unknown concrete class gives freedom to the implementors of the of methods.未知具体 class of方法的实现者提供了自由。

  • 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.这些程序员可以根据你的 arguments 的性质自由优化。例如,如果你传递的是枚举 arguments,则可能会在后台使用高度优化的EnumSet class。
  • 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.这些程序员可以在 Java 的版本之间自由更改他们的具体 class。例如,Java 17 实现可能返回一个具体的 class,而 Java 18 返回另一个。

So you should never depend on a particular concrete class being utilized by the of / copyOf methods.因此,您永远不应依赖of / copyOf方法所使用的特定具体 class。

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.在您的第一个中,我们知道具体的 class。结果集是可修改的。

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.在您的第二个中,我们不知道具体的 class,也不关心具体的 class。结果集是不可修改的。

Code代码 Concrete Class具体Class Modifiable可修改
new HashSet<>() {{ add("a");新的 HashSet<>() {{ add("a"); add("b");添加(“b”); add("c");添加(“c”); }} }} known已知的 modifiable可修改的
Set.of( "a", "b", "c" 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.如果您想要方便地对可修改集合进行紧凑的文字样式初始化,请结合使用of方法。 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.不保证由Set.of(...)产生的实现 class。 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.当您使用“双括号初始化”时,您正在定义一个从指定类型派生的新匿名 class。 So MySillyTest$1 extends HashSet because that's what you specified.所以MySillyTest$1扩展了HashSet因为那是你指定的。 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(...) .两者之间的重要区别是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(...) ;但是,即使您需要一个可变集,也不要将双括号初始化视为Set.of(...)的替代方案; just use a HashSet in the conventional way.只需以常规方式使用HashSet即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如果元素是重复的,为什么Set.of()会抛出IllegalArgumentException? - Why does Set.of() throw an IllegalArgumentException if the elements are duplicates? 有没有办法使用 IntelliJ 重构 Set 初始化以使用 Set.of()? - Is there a way to refactor a Set initialization to use Set.of() using IntelliJ? 关于使用 hashset 定义新集合的问题 - questions on using hashset to define a new set JDK 11 Generics 使用 Set.of 时的问题 - JDK 11 Generics Issue when using Set.of 默认情况下,DozerMapper映射,设置为HashSet会破坏元素的顺序 - DozerMapper maps by default, Set to HashSet which destroys the ordering of elements 来自 Set.of(...) 的随机迭代顺序 - Random Iteration order from Set.of(…) 为什么 LinkedHashSet<E> 扩展哈希集<e>并实现 Set<E> - Why does LinkedHashSet<E> extend HashSet<e> and implement Set<E> 如何在Java 9 Set.of中保持顺序 - How to keep order in Java 9 Set.of 使用工厂方法Set.of()和Map.of()创建的集合和地图的时间复杂度是多少? - What is a time complexity for sets and maps created with a factory methods Set.of() and Map.of()? 将集合类型转换为 HashSet 和使用集合初始化 HashSet 有什么区别? - What is the difference between type casting a set to HashSet and initializing a HashSet with a set?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM