【问题标题】:What is the best way in terms of space efficiency to make a List of objects immutable?就空间效率而言,使对象列表不可变的最佳方法是什么?
【发布时间】:2021-09-08 13:48:47
【问题描述】:

37:19 of this talk by Stuart Marks on Java Collections 提供的示例的提示下,我想知道从空间效率的角度来看,使对象列表不可变的最佳方法是什么。

在我的示例中,我有一个从数据库中检索的对象列表:

List<MyObject> myObjects = myRepository.getMyObjectsThatFitCriteria();

为了使这个列表不可变,我可以想到三种方法来做到这一点

  1. 将其包装在 Collections.unModifiableList() 中,但这会创建另一个对象,并且底层列表本身仍然可以修改
  2. 流过myObjects 列表并将其收集到一个不可修改的列表中,但这可能会影响性能,尤其是在列表很大的情况下
  3. 使用 Java 9 中引入的 List.copyOf() 静态工厂方法,但这会创建 myObjects 列表的另一个副本,从而影响内存和存储。

【问题讨论】:

  • Collections.unmodifiableList 创建了一个无关紧要的轻量级包装器。并且原始 List 不会被存储库修改,因此除非您自己的代码打算修改它,否则它永远不会被修改。 List.copyOf 是一样的。请记住,新 List 不会创建新对象,只会引用相同的元素。

标签: java list collections


【解决方案1】:

正如@VGR 在评论中提到的那样,Collections.unmodifiableList 不会将元素复制到新列表中,而是将其包装起来并防止对其进行修改。

如果您使用 Spring Data JPA 来支持存储库,最好利用它对流的支持:https://www.baeldung.com/spring-data-java-8

如果列表很大,流是避免大量内存消耗的好方法。它不改变源集合,允许懒惰消费。

【讨论】:

    【解决方案2】:

    将它包装在 Collections.unModifiableList() 中,但这会创建另一个对象,并且底层列表本身仍然是可修改的。

    您仍然需要创建一个列表,所以没有办法解决这个问题。但您始终可以重新分配到同一个列表,以有效地从访问权限中删除引用。

    list = Collections.unModifiableList(list);
    

    对于像size() 这样的不可变方法,原始列表在内部只是简单地引用(因此不是复制)。任何其他允许更改的方法都会被调用时抛出异常的方法覆盖。所以开销很小。

    请注意,除非包含的对象是不可变的,否则它们仍然可以更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-12
      • 2015-01-09
      • 2017-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-16
      • 1970-01-01
      相关资源
      最近更新 更多