在本教程中,我们将学习如何将Java流中的元素收集到一个不可变的集合或不可修改的集合中。
1.使用Collectors.collectingAndThen()- Java 8
Collectors.collectingAndThen()在Java 8中作为lambda表达式变化的一部分被引入。这个方法需要两个参数,一个是收集器,一个是整理函数。
Arrays.asList(1, 2, 3, 4, 5)
.stream()
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
我们可以将上述函数分解为两个步骤。
- Collectors.toList()会将Stream收集成一个可修改的List。
- **Collections.unmodifiableList()**将可变的List转换为不可变的List类型 java.util.Collections$UnmodifiableRandomAccessList.
我们可以把这两个步骤分别写下来,如下。
List<Integer> mutableList = Arrays.asList(1, 2, 3, 4, 5)
.stream()
.collect(Collectors.toList());
List<Integer> unmodifiableList = Collections.unmodifiableList(mutableList);
2.使用Collectors.toUnmodifiableList()- Java 10
该 Collectors.toUnmodifiableList()是Java 10中引入的一个静态函数。这是之前解决方案的一个捷径,它分两步将Stream收集成一个不可修改的List。
它返回一个类型为 java.util.ImmutableCollections$ListN并在遇到任何空值时抛出一个NullPointerException。请注意,ImmutableCollections是各种不可变集合的一个容器类。
var unmodifiableList = Stream.of(1, 2, 3, 4, 5)
.collect(Collectors.toUnmodifiableList());
我们可以使用 Collectors.toUnmodifiableSet()将把Stream元素收集到一个不可修改的Set中。
var unmodifiableSet = Stream.of(1, 2, 3, 4, 5)
.collect(Collectors.toUnmodifiableSet());
同样地,我们可以用 Collectors.toUnmodifiableMap()来收集元素到一个不可修改的Map中。它需要两个参数。
- 一个键映射函数,用于映射地图中的键
- 一个值映射函数,它将映射相应键的值。
在下面的例子中,我们将创建一个Map,以List中的整数为键,以整数的平方为值。
var unmodifiableMap = Stream.of(1, 2, 3, 4, 5).collect(Collectors.toUnmodifiableMap(i -> i, i -> i * i));
3.使用Stream.toList()- Java 16
在Java 16中,Stream接口引入了一个新的默认方法 toList()它返回一个不可变的List。
var unmodifiableList = Stream.of(1, 2, 3, 4, 5)
.toList();
4.使用谷歌的Guava库
由于Guava是一个外部库,它必须被添加到你的classpath中。如果你使用的是Maven,请按如下步骤添加Guava依赖项。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
4.1.使用ImmutableList.toImmutableList()
从Guava v21.0开始,我们可以使用*ImmutableList.toImmutableList()*静态方法,将元素收集到一个Immutable List中。
ImmutableList.toImmutableList()方法返回一个类型为 com.google.common.collection.RegularImmutableList并在遇到任何空值时抛出一个NullPointerException。
var unmodifiableList = Stream.of(1, 2, 3, 4, 5)
.collect(ImmutableList.toImmutableList());
4.2.使用Collectors.collectionAndThen()与ImmutableList::copyOf
这种方法与上面描述的方法类似。在这里,相反,我们用 ImmutableList::copyOf作为终结函数。
var unmodifiableList = Stream.of(1, 2, 3, 4, 5)
.collect(Collectors.collectingAndThen(Collectors.toList(), ImmutableList::copyOf));
5.不可变与不可修改的集合
不支持修改操作的集合被称为不可修改的。不可修改的集合通常是其他可变集合的只读视图(包装)。我们不能添加、删除或清除它们,但如果我们改变了底层集合,这个集合的视图也会被改变。
额外保证底层集合对象的变化不会被发现的集合被称为不可变的。
我们完全不能改变不可变的集合--它们不会包裹另一个集合--它们有自己的元素。
6.总结
这个Java集合教程探讨了将Java流转换为不可变的集合的各种方法。建议使用我们正在使用的最新Java版本中的解决方案。