google的ImmutableList和Collections.unmodifiableList()有什么区别?

Rom*_*man 49 java collections comparison guava

来自ImmutableList javadocs:

与Collections.unmodifiableList(java.util.List)不同,后者是一个仍然可以更改的单独集合的视图,ImmutableList的实例包含其自己的私有数据,并且永远不会更改.ImmutableList方便公共静态最终列表("常量列表"),还可以让您轻松地为调用者提供给您的类的列表的"防御性副本".

这是否意味着:

  1. 如果我有Dimension对象的ImmutableList(例如),那么我不能更改其中的任何Dimension对象?
  2. 如果我有Dimension对象的Collections.unmodifiableList(列表),那么我不仅可以添加或删除任何对象,但我可以更改它们(例如调用setDimension(width,height)方法)?

Yis*_*hai 54

不,不变性仅适用于Collection中对象的数量和引用,并不解决您在Collection中放置的对象的可变性.

不可变列表比标准JDK Collections.unmodifiableList获得的是通过使用ImmutableList保证引用的对象,它们的顺序和列表大小不能从任何源更改.使用Collections.unmodifiableList,如果其他内容具有对基础列表的引用,即使您具有对不可修改列表的引用,该代码也可以修改该列表.

但是,如果您想要真正的不变性,则必须使用不可变对象填充列表.

  • @Vuntic,当我尝试修改最终字段而不设置setAccessable时,我收到异常.你在想什么?顺便说一下,这个问题也没有提到反思;) (5认同)
  • @Yishai,反射*可以*修改最终字段。尝试一下。 (4认同)
  • @Yishai我知道我这次谈话已经晚了7年......但是对于公共记录,你首先使用反射来删除最终修饰符来修改最终字段.它只适用于对象,而不适用于基元. (2认同)

z5h*_*z5h 17

使用Collections.unmodifiableList在List周围创建一个包装器.如果基础列表发生了变化,那么你的unmodifiableList视图也会发生变化.

正如文档所述,Google的代码会创建一个副本.这是一个更昂贵的计算并消耗更多的内存,但如果有人改变原始列表,它不能影响ImmutableList.

这些都不会阻止您更改列表中的对象,或者字段或字段等.

  • "正如文档所说,Google的代码创建了一个副本." 它*可能*创建一个副本.如果原始数据也是一个不可变的数据结构,它实际上可以重用它.因此,如果你广泛使用`ImmutableList`,你会经常遇到这种情况,最终不必复制很多. (2认同)

Kit*_*YMG 6

ImmutableList类似于Collections.unmodifiableList( new ArrayList( list ) ).请注意,新创建ArrayList不会分配给字段或变量.