Dar*_*iva 3 java instanceof java-stream
假设我们有一个动物流。
我们有不同的动物子类,并且我们希望在流上应用过滤器以仅包含流中的斑马。我们现在仍然有动物流,但只包含斑马。为了获得斑马流,我们仍然需要进行投射。
Stream<Zebra> zebraStream = animalStream
.filter(Zebra.class::isInstance)
.map(Zebra.class::cast);
Run Code Online (Sandbox Code Playgroud)
Java 14 引入了instanceof 的模式匹配,所以我们现在可以使用:
if (animal instanceof Zebra zebra) {
System.out.println(zebra.countStripes());
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在流管道中使用模式匹配?当然你可以这样做:
Stream<Zebra> zebraStream = animalStream.map(animal -> {
if (animal instanceof Zebra zebra) {
return zebra;
}
return null;
})
.filter(Objects::nonNull);
Run Code Online (Sandbox Code Playgroud)
但恕我直言,这真的很难看。
要将超类型的 Stream 强制为其子类型之一的 Stream,您可以将instanceof 的模式匹配与 Java 16 结合使用mapMulti(),它需要一个流元素和一个Consumer结果类型:
Stream<Animal> animalStream = Stream.of();
Stream<Zebra> zebraStream = animalStream
.mapMulti((animal, consumer) -> {
if (animal instanceof Zebra zebra) consumer.accept(zebra);
});
Run Code Online (Sandbox Code Playgroud)
要对 instanceof 使用模式匹配,您还可以使用经典的流操作flatMap(),这就像mapMulti()执行一对多转换。
两者之间的重要区别在于,通过其mapMulti()将初始流元素替换为零个或多个Consumer元素,同时flatMap()需要生成一个新的流来压平数据。在这种情况下,利用mapMulti()会更有优势,因为如果列表很大,为每个元素生成单例流可能会很昂贵。
Stream<Zebra> zebraStream = animalStream
.flatMap(animal ->
animal instanceof Zebra zebra ? Stream.of(zebra) : null
);
Run Code Online (Sandbox Code Playgroud)
请注意,根据文档,我们也可以返回而不是空流null(这很方便,因为 Stream.empty() 不返回常量,而是生成一个新对象):
如果映射流是
null空流,则使用空流。
| 归档时间: |
|
| 查看次数: |
598 次 |
| 最近记录: |