Collections.unmodifiableSet()和Guava的ImmutableSet有什么区别?

时间:2021-09-24 15:50:41

JavaDoc of ImmutableSet says:

ImmutableSet的JavaDoc说:

Unlike Collections.unmodifiableSet, which is a view of a separate collection that can still change, an instance of this class contains its own private data and will never change. This class is convenient for public static final sets ("constant sets") and also lets you easily make a "defensive copy" of a set provided to your class by a caller.

与Collections.unmodifiableSet不同,Collections.unmodifiableSet是可以更改的单独集合的视图,此类的实例包含其自己的私有数据,并且永远不会更改。这个类对于公共静态最终集(“常量集”)很方便,也可以让你轻松地为调用者提供给你的类的集合制作一个“防御性副本”。

But the ImmutableSet still stores reference of elements, I couldn't figure out the difference to Collections.unmodifiableSet(). Sample:

但是ImmutableSet仍然存储元素的引用,我无法弄清楚Collections.unmodifiableSet()的区别。样品:

StringBuffer s=new StringBuffer("a");
ImmutableSet<StringBuffer> set= ImmutableSet.of(s);
s.append("b");//s is "ab", s is still changed here!

Could anyone explain it?

谁能解释一下呢?

4 个解决方案

#1


72  

Consider this:

Set<String> x = new HashSet<String>();
x.add("foo");

ImmutableSet<String> guava = ImmutableSet.copyOf(x);
Set<String> builtIn = Collections.unmodifiableSet(x);

x.add("bar");
System.out.println(guava.size()); // Prints 1
System.out.println(builtIn.size()); // Prints 2

In other words, ImmutableSet is immutable despite whatever collection it's built from potentially changing - because it creates a copy. Collections.unmodifiableSet prevents the returned collection from being directly changed, but it's still a view on a potentially-changing backing set.

换句话说,ImmutableSet是不可变的,尽管它可能通过改变而构建它的任何集合 - 因为它创建了一个副本。 Collections.unmodifiableSet可以防止直接更改返回的集合,但它仍然是可能更改的后备集的视图。

Note that if you start changing the contents of the objects referred to by any set, all bets are off anyway. Don't do that. Indeed, it's rarely a good idea to create a set using a mutable element type in the first place. (Ditto maps using a mutable key type.)

请注意,如果您开始更改任何集合引用的对象的内容,则无论如何都会关闭所有投注。不要那样做。实际上,首先使用可变元素类型创建集合并不是一个好主意。 (使用可变密钥类型的Ditto映射。)

#2


15  

Besides the behavioral difference that Jon mentions, an important difference between ImmutableSet and the Set created by Collections.unmodifiableSet is that ImmutableSet is a type. You can pass one around and have it remain clear that the set is immutable by using ImmutableSet rather than Set throughout the code. With Collections.unmodifiableSet, the returned type is just Set... so it's only clear that the set is unmodifiable at the point where it is created unless you add Javadoc everywhere you pass that Set saying "this set is unmodifiable".

除了Jon提到的行为差异之外,ImmutableSet和Collections.unmodifiableSet创建的Set之间的一个重要区别是ImmutableSet是一种类型。你可以传递一个,并且通过使用ImmutableSet而不是整个代码中的Set来保持集合是不可变的。使用Collections.unmodifiableSet,返回的类型只是Set ...所以只有在创建它时,该组才是不可修改的,除非您在传递该Set的任何地方添加Javadoc,说“此set是不可修改的”。

#3


10  

Kevin Bourrillion (Guava lead developer) compares immutable / unmodifiable collections in this presentation. While the presentation is two years old, and focuses on "Google Collections" (which is now a subpart of Guava), this is a very interesting presentation. The API may have changed here and there (the Google Collections API was in Beta at the time), but the concepts behind Google Collections / Guava are still valid.

Kevin Bourrillion(Guava首席开发人员)在此演示文稿中比较了不可变/不可修改的集合。虽然演示文稿已有两年历史,并专注于“Google Collections”(现在是Guava的子部分),但这是一个非常有趣的演示。 API可能已经在那里发生了变化(Google Collections API当时处于测试阶段),但Google Collections / Guava背后的概念仍然有效。

You might also be interested in this other SO question ( What is the difference between google's ImmutableList and Collections.unmodifiableList() ).

您可能也对其他SO问题感兴趣(google的ImmutableList和Collections.unmodifiableList()之间有什么区别)。

#4


2  

A difference between the two not stated in other answers is that ImmutableSet does not permit null values, as described in the Javadoc

其他答案中未说明的两者之间的差异是ImmutableSet不允许空值,如Javadoc中所述

A high-performance, immutable Set with reliable, user-specified iteration order. Does not permit null elements.

具有可靠的,用户指定的迭代顺序的高性能,不可变集合。不允许null元素。

(The same restriction applies to values in all Guava immutable collections.)

(同样的限制适用于所有Guava不可变集合中的值。)

For example:

ImmutableSet.of(null);
ImmutableSet.builder().add("Hi").add(null); // Fails in the Builder.
ImmutableSet.copyOf(Arrays.asList("Hi", null));

All of these fail at runtime. In contrast:

所有这些都在运行时失败。相反:

Collections.unmodifiableSet(new HashSet<>(Arrays.asList("Hi", null)));

This is fine.

这可以。

#1


72  

Consider this:

Set<String> x = new HashSet<String>();
x.add("foo");

ImmutableSet<String> guava = ImmutableSet.copyOf(x);
Set<String> builtIn = Collections.unmodifiableSet(x);

x.add("bar");
System.out.println(guava.size()); // Prints 1
System.out.println(builtIn.size()); // Prints 2

In other words, ImmutableSet is immutable despite whatever collection it's built from potentially changing - because it creates a copy. Collections.unmodifiableSet prevents the returned collection from being directly changed, but it's still a view on a potentially-changing backing set.

换句话说,ImmutableSet是不可变的,尽管它可能通过改变而构建它的任何集合 - 因为它创建了一个副本。 Collections.unmodifiableSet可以防止直接更改返回的集合,但它仍然是可能更改的后备集的视图。

Note that if you start changing the contents of the objects referred to by any set, all bets are off anyway. Don't do that. Indeed, it's rarely a good idea to create a set using a mutable element type in the first place. (Ditto maps using a mutable key type.)

请注意,如果您开始更改任何集合引用的对象的内容,则无论如何都会关闭所有投注。不要那样做。实际上,首先使用可变元素类型创建集合并不是一个好主意。 (使用可变密钥类型的Ditto映射。)

#2


15  

Besides the behavioral difference that Jon mentions, an important difference between ImmutableSet and the Set created by Collections.unmodifiableSet is that ImmutableSet is a type. You can pass one around and have it remain clear that the set is immutable by using ImmutableSet rather than Set throughout the code. With Collections.unmodifiableSet, the returned type is just Set... so it's only clear that the set is unmodifiable at the point where it is created unless you add Javadoc everywhere you pass that Set saying "this set is unmodifiable".

除了Jon提到的行为差异之外,ImmutableSet和Collections.unmodifiableSet创建的Set之间的一个重要区别是ImmutableSet是一种类型。你可以传递一个,并且通过使用ImmutableSet而不是整个代码中的Set来保持集合是不可变的。使用Collections.unmodifiableSet,返回的类型只是Set ...所以只有在创建它时,该组才是不可修改的,除非您在传递该Set的任何地方添加Javadoc,说“此set是不可修改的”。

#3


10  

Kevin Bourrillion (Guava lead developer) compares immutable / unmodifiable collections in this presentation. While the presentation is two years old, and focuses on "Google Collections" (which is now a subpart of Guava), this is a very interesting presentation. The API may have changed here and there (the Google Collections API was in Beta at the time), but the concepts behind Google Collections / Guava are still valid.

Kevin Bourrillion(Guava首席开发人员)在此演示文稿中比较了不可变/不可修改的集合。虽然演示文稿已有两年历史,并专注于“Google Collections”(现在是Guava的子部分),但这是一个非常有趣的演示。 API可能已经在那里发生了变化(Google Collections API当时处于测试阶段),但Google Collections / Guava背后的概念仍然有效。

You might also be interested in this other SO question ( What is the difference between google's ImmutableList and Collections.unmodifiableList() ).

您可能也对其他SO问题感兴趣(google的ImmutableList和Collections.unmodifiableList()之间有什么区别)。

#4


2  

A difference between the two not stated in other answers is that ImmutableSet does not permit null values, as described in the Javadoc

其他答案中未说明的两者之间的差异是ImmutableSet不允许空值,如Javadoc中所述

A high-performance, immutable Set with reliable, user-specified iteration order. Does not permit null elements.

具有可靠的,用户指定的迭代顺序的高性能,不可变集合。不允许null元素。

(The same restriction applies to values in all Guava immutable collections.)

(同样的限制适用于所有Guava不可变集合中的值。)

For example:

ImmutableSet.of(null);
ImmutableSet.builder().add("Hi").add(null); // Fails in the Builder.
ImmutableSet.copyOf(Arrays.asList("Hi", null));

All of these fail at runtime. In contrast:

所有这些都在运行时失败。相反:

Collections.unmodifiableSet(new HashSet<>(Arrays.asList("Hi", null)));

This is fine.

这可以。