如何将Java流中的元素收集到一个不可变的集合或不可修改的集合中

417 阅读2分钟

在本教程中,我们将学习如何将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版本中的解决方案。