我想问 - 有什么区别
Set<CurrencyType> set1 = new HashSet<>() {{
add("a");
add("b");
add("c");
}}
和
Set<CurrencyType> set2 = Set.of(
"a",
"b",
"c"
)
在名为
MySillyTest
的@Test调试模式下(这个名称很快就会回来),我可以看到set1
是MySillyTest$1
的一个实例,但我认为它只是一个HashSet
。另一方面,set2
是 ImmutableCollections$SetN
的一个实例。这两者之间真正的区别是什么? java.util.Set
使用什么 Set.of()
实现?这两者之间有性能/内存使用/CPU 使用差异吗?
Set.of
(和List.of
、Map.of
)使用的具体类没有记录。我们所知道的是返回的对象 (a) 实现了接口,并且 (b) 是不可修改的。
这就是我们需要知道的一切。我们不应该关心幕后使用的特定具体类。
未知的具体类为
of
方法的实现者提供了自由。
EnumSet
类。因此,您应该永远不要依赖于of
/
copyOf
方法使用的特定具体类。
你问:
这两者之间的真正区别是什么?在你的第一个中,我们知道具体的类。并且结果集是可以修改的。
在你的第二个中,我们不知道具体的类,也不关心具体的类。并且结果集是不可修改的。
最好避免双括号初始化。
如果您想要方便地对可修改集合进行紧凑的文字样式初始化,请与of
方法结合使用。您可以将现有集合传递给构造函数。
Set< String > set =
new HashSet<>(
Set.of( "a", "b", "c" ) // Pass a collection to constructor.
)
;
“但我Set.of
。如上所述,实现细节可能会有所不同,因此您不应依赖于
Set.of
的特定实现。当您的项目有特定需求时,您应该明确选择满足这些需求的特定实现。您可以选择其中一种捆绑实现,从第三方库(例如
Eclipse Collections 或 Google Guava)获取一种实现,或者编写您自己的实现。
提示:您可以通过将其结果传递给所选实现的构造函数来利用Set.of
的便捷语法。请参阅上面的代码示例:
new HashSet<>( Set.of( … ) )
Set.of(...)
产生的实现类。它可能会根据运行时实现或未来版本而改变。然而,它的一些特性——主要是不变性——是得到保证的。当您使用“双括号初始化”时,您正在定义一个从指定类型派生的新匿名类。所以
MySillyTest$1
扩展了
HashSet
因为这就是您指定的。请注意,双括号初始化有问题;我不允许它,并且我不鼓励其他人使用它。 两者之间的重要区别是
Set.of(...)
带来的不变性。如果您需要一个可变集,那么这不是一个选择。但如果您可以使用不可变集,它会提供卓越的可读性和性能。但是,即使您需要可变集,也不要将双括号初始化视为
Set.of(...)
的替代方案;只需按照常规方式使用
HashSet
即可。