0

Suppose there is this code:

List<String> modifiableList = new ArrayList<String>(Arrays.asList("1","2","3"));
List<String> unmodifiableList = Collections.unmodifiableList(modifiableList);
System.out.println(unmodifiableList);
modifiableList.remove("1");
modifiableList.remove("3");
System.out.println(unmodifiableList);

it prints

[1, 2, 3]
[2]

If changing the second line to

List<String> unmodifiableList = Collections.unmodifiableList(
                                       new ArrayList<String>(modifiableList));

it works as expected. The question is why doesn't the UnmodifiableList inner class from Collections (and all the other unmodifiable classes) from there create a fresh copy of the original list, as does the constructor of ArrayList for example in order to really make it unmodifiable?

Edit: I understand what the code does; my question is why was it implemented this way? Why does the constructor from the UnmodifiableList (inner class from Collections) behave like the constructor of ArrayList in creating a fresh copy of the underlying array? Why a modifiable collection (ArrayList) copies the whole content while an unmodifiable collection doesn't?

4

3 回答 3

2

原因很简单,效率很高。复制集合的所有元素可能非常耗时,特别是如果被包装的集合具有某种魔法,例如 JPA 延迟加载,并且需要额外的内存。按原样包装基础集合是一项简单的操作,不会产生额外的开销。在开发人员确实想要一个单独的副本(不可修改或不可修改)的情况下,很容易显式地创建它。(我倾向于为此使用番石榴Immutable*。)

于 2014-02-06T13:29:28.997 回答
2

那么这些方法的目的是在现有集合上创建一个不可修改的视图。这是记录在案的行为,在许多情况下,这正是您想要的 - 例如,它比复制所有数据更有效......或者您想要反映您想要进行的任何更改的调用者集合交给,但不允许他们做出改变。

如果您想要数据的不可变副本(或至少是引用......),那么只需创建一个副本,然后在其顶部创建一个不可变视图 - 就像您一样。

因此,基本上,您可以根据Collections.unmodifiable*自己执行视图操作轻松创建视图或复制和视图。所以我们有两个正交操作:

  • 创建一个副本(例如通过构造函数)
  • 创建视图(通过Collections.unmodifiable*

这些操作可以很容易地组合。如果实际上执行了“Collections.unmodifiable*复制”,那么我们需要其他操作才能制作视图。如果您接受这两个选项在不同情况下都有用,那么使它们可组合会带来很大的灵活性。

于 2014-02-06T13:30:00.810 回答
0

请注意,unmodifiableList 返回提供列表的“不可修改视图”。所以列表本身保持不变(它仍然可以修改),只有它的“不可修改视图”是不可修改的。您可以将其视为 SQL 表和视图 --- 您可以在表上运行 DML 脚本,它将反映在相关视图上。至于 ArrayList ---它由...支持一个数组,因此它是实现功能,它从提供的源列表中复制元素(实际上不必由数组支持)。它回答了你的问题吗?

于 2014-02-06T13:37:11.467 回答