【问题标题】:What is the difference between google's ImmutableList and Collections.unmodifiableList ()?google 的 ImmutableList 和 Collections.unmodifiableList() 有什么区别?
【发布时间】:2011-01-12 05:58:52
【问题描述】:

来自 ImmutableList javadocs:

不像 Collections.unmodifiableList(java.util.List), 这是一个单独的视图 仍然可以改变的收藏,一个 ImmutableList 的实例包含其 拥有私人数据,永远不会 改变。 ImmutableList 很方便 用于公共静态最终列表 (“常量列表”),还可以让您 轻松制作一个“防御性副本” 由 a 提供给您的班级的列表 来电者。

是不是意味着:

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

【问题讨论】:

标签: java collections comparison guava


【解决方案1】:

不,不变性只适用于Collection中对象的数量和引用,不解决您放入Collection中的对象的可变性。

与标准 JDK Collections.unmodifiableList 相比,不可变列表的优势在于,通过使用 ImmutableList,您可以保证引用的对象、它们的顺序和列表的大小不会因任何来源而改变。使用Collections.unmodifiableList,如果其他内容引用了基础列表,即使您引用了不可修改的列表,该代码也可以修改列表。

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

【讨论】:

  • @Vuntic,如果类是真正不可变的,它的字段被声明为 final,反射不能改变它。
  • @Yishai,反射可以修改final字段。试试看。
  • @Vuntic,使用 setAccessible?这取决于安全经理;)。
  • @Vuntic,当我尝试修改最终字段而不设置 setAccessable 时出现异常。你在想什么?顺便说一句,这个问题也没有提到反射;)
  • @Yishai 我知道我在这次谈话中迟到了 7 年......但是为了公开记录,您首先使用反射删除 final 修饰符来修改 final 字段。但它只适用于对象,不适用于基元。
【解决方案2】:

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

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

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

【讨论】:

  • “正如文档所述,Google 的代码会创建一个副本。”它可能创建一个副本。如果原始数据结构也是不可变的数据结构,它实际上可能能够重用它。所以如果你广泛使用ImmutableList,你会经常遇到这种情况,最终不必复制太多。
【解决方案3】:

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

【讨论】:

    【解决方案4】:
    1. 不,包含的单个对象仍然可以修改。集合实际上只是存储对所包含对象的引用,而不是每个对象的完整副本。
    2. 您可以通过修改您在其上调用 Collections.unmodifiableList(list) 的父 Collection 来修改列表。但是,是的,您可以使用 setDimension 更改存储的列表元素。

    【讨论】:

      【解决方案5】:

      您可能还想看看this question(Guava 的Collections.unmodifiableSet() 和ImmutableSet 有什么区别)。

      【讨论】:

        猜你喜欢
        • 2013-05-15
        • 1970-01-01
        • 2014-02-27
        • 1970-01-01
        • 1970-01-01
        • 2018-03-08
        • 2019-09-01
        • 1970-01-01
        相关资源
        最近更新 更多