Collectors.toUnmodifiableList 对比 Collections.unmodifiableList 在 Java 10

Collectors.toUnmodifiableList vs Collections.unmodifiableList in Java 10

根据 doc 方法 Collections.unmodifiableList returns 指定列表的不可修改视图。返回的列表真的不可修改吗?不可修改的视图是什么意思?

根据 doc 方法 Collectors.toUnmodifiableList returns 一个收集器,它按遇到的顺序将输入元素累积到一个不可修改的列表中。这里返回的列表真的是不可修改的吗?

注意:可修改是指可以使用 set 操作修改视图。我想了解其中的区别以及它们之间的关系?

Collections.unmodifiableList returns 一个 unmodifiable view,这意味着调用返回的 List 的任何方法来改变 List 将抛出 UnsupportedOperationException .但是,传递给该方法的原始 List 仍然可以修改(假设它是可修改的),并且此类修改将反映在 Collections.unmodifiableList 返回的 List 中。因此,如果您无法访问原始List,则只能考虑"truly unmodifiable"。

另一方面,

Collectors.toUnmodifiableList 用于生成不可修改的新 List,因此无法修改 List。因此是"truly unmodifiable".

方法Collections.unmodifiableList returns 指定列表的不可修改视图。不可修改的视图集合是不可修改的集合,也是支持集合的视图。请注意,对支持集合的更改可能仍然是 可能,如果它们发生,它们通过不可修改的视图是可见的。

List<String> srcList = Arrays.asList("Apple", "Banana", "Cherry");
var fruits = new ArrayList<>(srcList);
var unmodifiableList = Collections.unmodifiableList(fruits);     
fruits.set(0, "Apricot");
var modFruit = unmodifiableList.get(0);
System.out.println(modFruit); // prints Apricot

我们可以在 Java10 及更高版本中拥有真正的不可变列表。有两种方法可以得到真正不可修改的列表如下图:

  1. var unmodifiableList = List.copyOf(srcList); => 打印 Apple
  2. var unmodifiableList = srcList.stream().collect(Collectors.toUnmodifiableList()); => 打印 Apple

所以方法 Collectors.toUnmodifiableList returns 一个真正不可修改的列表 List.of 在 Java 9 中引入。这个方法 returns a Collector where作为方法 Collections.unmodifiableList returns 一个列表。根据 doc,不可修改的列表具有以下特征:

  1. They are unmodifiable. Elements cannot be added, removed, or replaced. Calling any mutator method on the List will always cause UnsupportedOperationException to be thrown. However, if the contained elements are themselves mutable, this may cause the List's contents to appear to change.
  2. They disallow null elements. Attempts to create them with null elements result in NullPointerException.
  3. They are serializable if all elements are serializable.
  4. The order of elements in the list is the same as the order of the provided arguments, or of the elements in the provided array.
  5. They are value-based. Callers should make no assumptions about the identity of the returned instances. Factories are free to create new instances or reuse existing ones. Therefore, identity-sensitive operations on these instances (reference equality (==), identity hash code, and synchronization) are unreliable and should be avoided.
  6. They are serialized as specified on the Serialized Form page.

附带说明,Collectors.toUnmodifiableList 仅使用 java-9 中添加的 List::of 的实现,该实现的完成器是:

list -> (List<T>)List.of(list.toArray()

其中 list 只是一个 ArrayList;所以你的问题归结为 List::ofCollections::unmodifiableList 之间的区别是什么(当然需要注意的是,这没有指定并且在当前实施 下发生 ) 虽然我可以详细说明其中的一些差异,(如果您搜索的话还有更多)。

需要注意的一点是这些不同类型如何处理 nulls(另一点实际上是 view,已在其他答案中提供) :

List<Integer> left = Stream.of(1, 2, 3)
            .collect(Collectors.collectingAndThen(
                    Collectors.toList(),
                    Collections::unmodifiableList));

    System.out.println(left.contains(null));

    List<Integer> right = Stream.of(1, 2, 3)
            .collect(Collectors.toUnmodifiableList());

    System.out.println(right.contains(null)); 

最后一行代码会抛出异常,你可能根本没有想到。