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

发布于 2025-01-11 08:12:19 字数 563 浏览 2 评论 0 原文

我想问 -

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。另一方面,set2ImmutableCollections$SetN 的实例。这两者之间真正的区别是什么? Set.of() 使用的是 java.util.Set 的什么实现?这两者之间有性能/内存使用/CPU 使用差异吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

若相惜即相离 2025-01-18 08:12:19

不知道,不关心

Set.of (和 List.ofMap.of) 未记录。我们所知道的是返回的对象(a)实现了接口,并且(b)是不可修改的。

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

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

  • 这些程序员可以根据你的论点的性质自由地进行优化。例如,如果您传递枚举参数,则高度优化的 EnumSet 类可能在幕后使用。
  • 这些程序员可以在 Java 版本之间自由地更改他们的具体类。例如,Java 17 实现可能返回一个具体类,而 Java 18 返回另一个具体类。

因此,您不应该永远依赖于/copyOf 方法。

你问:

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

在你的第一个中,我们知道具体的类。并且结果集是可以修改的。

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

代码 具体类 可修改
new 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。如上所述,因此您不应依赖 Set.of 的特定实现。

当您的项目有特定需求时,您应该明确选择满足这些需求的特定实现。捆绑实现,从第三方库获取一个,例如 Eclipse CollectionsGoogle Guava,或编写您自己的。

提示:您可以利用 Set.of 的便捷语法,将其结果传递给所选实现的构造函数。请参阅上面的代码示例:

new HashSet<>( Set.of( … ) )

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( … ) )
生来就爱笑 2025-01-18 08:12:19

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

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文