Java 10中的Collectors.toUnmodifiableList与Collections.unmodifiableList

时间:2018-10-03 05:48:59

标签: java java-8 java-10

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

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

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

3 个答案:

答案 0 :(得分:8)

方法Collections.unmodifiableList返回指定列表的不可修改视图。不可修改的视图集合是不可修改的集合,并且也是支持集合的视图。请注意,对后备集合的更改可能仍然是 可能,并且如果它们发生,则可以通过不可修改的视图看到它们。

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

Java 10 及更高版本中,我们可以有一个真正的不可变列表。可以通过两种方法获取真正不可修改的列表,如下所示:

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

因此,方法Collectors.toUnmodifiableList返回Java 9中引入的真实的不可修改列表List.of。此方法返回Collector,其中方法Collections.unmodifiableList返回列表。根据{{​​3}},不可修改的列表具有以下特征:

  
      
  1. 它们是不可修改的。元素无法添加,删除或替换。调用List上的任何mutator方法总是会导致   UnsupportedOperationException被抛出。但是,如果包含   元素本身是可变的,这可能导致列表的内容   似乎改变了。
  2.   
  3. 它们不允许使用null元素。尝试使用空元素创建它们会导致NullPointerException
  4.   
  5. 如果所有元素都是可序列化的,则它们是可序列化的。
  6.   
  7. 列表中元素的顺序与提供的参数或数组中的元素的顺序相同。
  8.   
  9. 他们是value-based。调用者不应对返回实例的身份做任何假设。工厂可以自由创建新的   实例或重用现有实例。因此,身份敏感   这些实例上的操作(引用相等(==),标识哈希   代码和同步)是不可靠的,应避免使用。
  10.   
  11. 它们已按照“序列化表格”页面上的指定进行序列化。
  12.   

答案 1 :(得分:3)

Collections.unmodifiableList返回一个unmodifiable view,这意味着调用返回的List中使List发生突变的任何方法都会抛出UnsupportedOperationException。但是,传递给该方法的原始List仍然可以修改(假设它是可修改的),并且此类修改将反映在List返回的Collections.unmodifiableList中。因此,如果您无权访问原始List,则只能将其视为“真正不可修改”。

另一方面,

Collectors.toUnmodifiableList用于生成不可修改的新List,因此无法修改该List。因此,它是“真正不可修改的”。

答案 2 :(得分:1)

请注意,Collectors.toUnmodifiableList仅使用Java-9中添加的List::of的实现,该实现的完成者是:

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

其中list只是一个ArrayList;因此,您的问题仅归结为List::ofCollections::unmodifiableList之间的区别(当然,要注意的是,未指定该错误,并且在当前实现中发生),而我可以详细说明其中的一些差异,there are already good ones(如果您进行搜索,还会有更多差异)。

要注意的一点是这些不同类型如何处理null(其他答案中已经提供了另一个实际上是 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)); 

最后一行代码将引发Exception,您可能根本不会想到。