繁体   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<>()?

我想问 - 之间有什么区别

Set<CurrencyType> set1 = new HashSet<>() {{
    add("a");
    add("b");
    add("c");
}}

Set<CurrencyType> set2 = Set.of(
    "a",
    "b",
    "c"
)

在名为MySillyTest的 @Test 的调试模式下(这个名称很快就会恢复)我可以看到set1MySillyTest$1的一个实例,但我认为它只是一个HashSet 另一方面, set2ImmutableCollections$SetN的一个实例。 这两者之间的真正区别是什么? Set.of()使用的是java.util.Set的什么实现? 这两者之间是否存在性能/内存使用/cpu 使用差异?

不知道,不关心

Set.of (和List.ofMap.of )使用的具体 class 没有记录。 我们所知道的是返回的 object (a) 实现了接口,并且 (b) 是不可修改的。

这就是我们需要知道的全部。 我们不应该关心幕后使用的特定具体 class。

未知具体 class of方法的实现者提供了自由。

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

因此,您永远不应依赖of / copyOf方法所使用的特定具体 class。

您问:

这两者之间的真正区别是什么?

在您的第一个中,我们知道具体的 class。结果集是可修改的。

在您的第二个中,我们不知道具体的 class,也不关心具体的 class。结果集是不可修改的。

代码 具体Class 可修改
新的 HashSet<>() {{ add("a"); 添加(“b”); 添加(“c”); }} 已知的 可修改的
Set.of( "a", "b", "c" 未知 不可修改的

避免双括号

正如其他人所说,通常最好避免双括号初始化。

如果您想要方便地对可修改集合进行紧凑的文字样式初始化,请结合使用of方法。 您可以将现有集合传递给构造函数。

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

不保证由Set.of(...)产生的实现 class。 它可能会根据运行时实现或未来版本而改变。 然而,它的一些特性——主要是不变性——是有保证的。

当您使用“双括号初始化”时,您正在定义一个从指定类型派生的新匿名 class。 所以MySillyTest$1扩展了HashSet因为那是你指定的。 请注意,双括号初始化有问题; 我不允许,我也不鼓励其他人使用它。

两者之间的重要区别是Set.of(...)产生的不变性。 如果您需要一个可变集,那不是一个选择。 但是,如果您可以使用不可变集,它会提供卓越的可读性和性能。

但是,即使您需要一个可变集,也不要将双括号初始化视为Set.of(...)的替代方案; 只需以常规方式使用HashSet即可。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM