0

我不确定我理解的不可变集合的缺陷是否正确,所以我在这个答案中列出了它们。希望有人在这里纠正我。

a):与 Collections.unmodifiableXXX() 相比,ImmutableXXX.copyOf()失去了源集合特性。例如,当将linkedList 放入ImmutableList.copyOf() 时,ImmutableList 不再链接。与基于树的集合相同。

b):人们认为 Collections.unmodifiableXXX 只是使用了源集合的相同引用,所以一旦源集合改变,Collections.unmodifiableXXX 也会改变。但我的解决方案是将源集合包装到传递给 ImmutableXXX.copyOf() 的临时集合中。请参见下面的代码:

List<String> l = new ArrayList<String>();
List<String>  unmodifiableList = Collections.unmodifiableList(l);
ImmutableList<String> immutableList= ImmutableList.copyOf(l);
l.add("a");//unmodifiableList is also added "a", immutableList not.

/*My solution as follows:
So unmodifiableList2 is also immutable as ImmutableList.copyOf(l) does*/
List<String> unmodifiableList2= Collections.unmodifiableList(new ArrayList(l));

你对不可变集合的理解是什么?谢谢!

4

3 回答 3

21

您提到的任何内容都不是“缺陷”。

a)ImmutableList an不再是链表并不重要。与基于数组的列表相比,链表的唯一优势在于添加和删除元素(主要是删除)。您不能在不可变列表中添加或删除,因此基于数组的快速随机访问和内存效率更可取。

对于类似的东西TreeSet,有很多点需要考虑。

  1. 法线ImmutableSet保留给定元素的迭代顺序。因此,如果您有一个TreeSet和使用ImmutableSet.copyOf来创建不可变副本,则复制的元素将按照与原始元素相同的顺序排列。
  2. ImmutableSortedSet是不可变的等价物TreeSet并使用元素的自然顺序或Comparator类似TreeSet的。

b)您可以在不使用 Guava 的情况下创建一个List恰好是不可变的事实并不会改变任何事情。Guava 的不可变集合在设计时特别考虑了不可变性,因此它们具有各种优势,包括(但不限于):

  • 正如我在回答您上一个问题时提到的那样,它们的不变性在类型级别得到保证。当你的方法返回 typeImmutableSet的东西时,调用者知道set 不能改变它们。如果它只是返回,则不是这样Set
  • 内存优化,包括用于空情况的单例和用于 1 元素情况的特殊类。
  • ImmutableSet.copyOf如果输入已经是相同类型的不可变实例等,则实际上不会复制任何内容。
  • 使创建不可变集合变得容易的方法/构建器。
于 2011-04-11T03:23:09.780 回答
4

为什么我们需要不可变集合

  • 它极大地简化了并发编程。想一想,为什么编写正确的多线程编程很难?因为很难同步线程访问给定资源(在本例中为列表)。
于 2011-04-11T03:13:48.613 回答
3

ColinD 和 Amir 直接回答了您的具体问题,但您可能还想查看GTUG - Using the Google Collections Library for Java (1 of 2) - Kevin Bourrillion(Guava 的首席开发人员)关于不可变集合的演示,他解释了所有不可变集合的优点。

虽然该演示文稿已有两年之久,并且侧重于“Google Collections”(现在是 Guava 的一个子部分),但这是一个非常有趣的演示文稿。自演示以来,该 API 可能发生了一些变化,因为当时 Google Collections API 处于测试阶段,但大多数概念保持不变。

于 2011-04-11T06:03:03.333 回答