ImmutableSet
的JavaDoc说:
与
Collections.unmodifiableSet
不同,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!
的区别。样品:
{{1}}
有人可以解释一下吗?
答案 0 :(得分:78)
考虑一下:
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
换句话说,ImmutableSet
是不可变的,尽管它可能通过可能改变而构建的集合 - 因为它创建了一个副本。 Collections.unmodifiableSet
阻止返回的集合直接更改,但它仍然是可能更改的后备集的视图。
请注意,如果您开始通过任何设置更改引用对象的内容,则无论如何都会关闭所有投注。不要那样做。实际上,首先使用可变元素类型创建集合并不是一个好主意。 (使用可变密钥类型进行Ditto映射。)
答案 1 :(得分:15)
除了Jon提到的行为差异之外,ImmutableSet
与Set
创建的Collections.unmodifiableSet
之间的重要区别在于ImmutableSet
是类型。您可以传递一个,并且通过在整个代码中使用ImmutableSet
而不是Set
来清楚地表明该集是不可变的。对于Collections.unmodifiableSet
,返回的类型只是Set
...因此,只有在创建它时,该集合才可以无法修改,除非您在传递Set
所说的任何地方添加Javadoc “这套不可修改”。
答案 2 :(得分:10)
Kevin Bourrillion(Guava首席开发人员)在this presentation中比较了不可变/不可修改的集合。虽然演示文稿已有两年历史,并专注于“Google Collections”(现在是Guava的子部分),但这是一个非常有趣的演示文稿。 API可能已经发生变化(Google Collections API当时处于测试阶段),但Google Collections / Guava背后的概念仍然有效。
您可能也对this other SO question感兴趣( Google的ImmutableList和Collections.unmodifiableList()之间有什么区别。)
答案 3 :(得分:3)
其他答案中未说明的两者之间的差异是ImmutableSet
不允许null
值,如Javadoc
具有可靠的,用户指定的迭代顺序的高性能,不可变集合。不允许使用null元素。
(同样的限制适用于所有Guava不可变集合中的值。)
例如:
ImmutableSet.of(null);
ImmutableSet.builder().add("Hi").add(null); // Fails in the Builder.
ImmutableSet.copyOf(Arrays.asList("Hi", null));
所有这些都在运行时失败。相反:
Collections.unmodifiableSet(new HashSet<>(Arrays.asList("Hi", null)));
这很好。