List.of(...) 或 Collections.unmodifiableList()

2022-09-03 01:20:01

如果你有一个实例,你会继续写:List<String> strings

Collections.unmodifiableList(strings)

或切换到:

List.of(strings.toArray(new String[strings.size()]))

对实例化的性能(内存和运行时方面)的初始影响是什么?变体中是否有运行时优势?List.of


答案 1

这并不是一个很好的比较,因为这些方法做不同的事情:

  • Collections::unmodifiable...创建不可修改的视图。它不是可变的,因为如果您要更改原始的支持集合(在您的示例中),它会发生变化。list
  • ...::of另一方面,创建不可变副本。更改原始列表不会影响它。

从性能的角度来看,创建不可修改的包装器显然更便宜,因为它只创建一个具有单个字段的实例。新的工厂方法将创建至少一个对象,该对象可能由数组(如果您有三个或更多元素)支持,它需要复制到其中。

在新的不可变集合上访问速度可能更快,但这必须进行基准测试。

但正确性胜过性能。您需要什么?如果您需要不可变的副本,请使用新方法(或番石榴,我更喜欢)。如果你需要一些不可变的东西,使用并扔掉原件(并确保它保持原样)。如果需要调用方无法编辑的视图,请使用 。Immutable...unmodifiable...unmodifiable...


答案 2

根据 JEP 269(便利工厂收集方法):

目标

在集合接口上提供静态工厂方法,这些方法将创建紧凑、不可修改的集合实例。API 被特意保持在最小值。

非目标

  • 提供完全通用的“集合生成器”工具不是目标,例如,允许用户控制集合实现或各种特征,如可变性、预期大小、加载因子、并发级别等。

  • 支持具有任意数量元素的高性能、可缩放集合不是目标。重点是小型集合。

  • 提供不可修改的集合类型不是目标。也就是说,此建议不会暴露类型系统中不可修改性的特征,即使建议的实现实际上是不可修改的。

  • 提供“不可变的持久”或“功能性”集合不是目标。