我不确定我了解的不可变集合的缺陷是正确的,因此我在此答案中列出了它们。希望有人在这里纠正我。
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));
您对不可变集合有什么理解?谢谢!
最佳答案
您没有提到的是“缺陷”。
a)ImmutableList
不再是链接列表完全没有关系。与基于数组的列表相比,链表的唯一优点包括添加和删除元素(主要是删除)。您不能在不可变列表中添加或删除,因此基于数组的数组由于其快速的随机访问以及内存效率而更可取。
对于TreeSet
之类的东西,要考虑一些要点。
普通ImmutableSet
保留给定元素的迭代顺序。因此,如果您有TreeSet
并使用ImmutableSet.copyOf
创建不可变副本,则复制的元素的顺序将与原始顺序相同。ImmutableSortedSet
是TreeSet
的不变变量,并且像Comparator
一样使用元素或TreeSet
的自然顺序。
b)您可以创建不使用番石榴而恰好是不变的List
的事实,不会改变任何东西。番石榴的不可变集合是专门为不可变而设计的,因此具有各种优势,包括(但不限于):
正如我在对上一个问题的回答中所提到的,在类型级别上保证了它们的不变性。当您的方法返回类型为ImmutableSet
的东西时,调用者知道该集合无法更改。如果仅返回Set
,则不是这样。
内存优化,包括针对空情况的单例和针对1元素情况的特殊类。ImmutableSet.copyOf
等。如果输入已经是相同类型的不可变实例,则实际上不复制任何内容。
易于创建不可变集合的方法/构建器。