gpt4 book ai didi

java - 在 Stream 中为 Instanceof 应用模式匹配

转载 作者:行者123 更新时间:2023-12-05 01:49:11 27 4
gpt4 key购买 nike

假设我们有一条动物流。

我们有不同的动物子类,我们想在流上应用过滤器以仅拥有流中的斑马。我们现在仍然有一个动物流,但只包含斑马。要获得斑马流,我们仍然需要进行转换。

Stream<Zebra> zebraStream = animalStream
.filter(Zebra.class::isInstance)
.map(Zebra.class::cast);

Java 14 为 instanceof 引入了模式匹配,所以我们现在可以使用:

if (animal instanceof Zebra zebra) {
System.out.println(zebra.countStripes());
}

有没有办法在流管道中使用模式匹配?当然你可以这样做:

Stream<Zebra> zebraStream = animalStream.map(animal -> {
if (animal instanceof Zebra zebra) {
return zebra;
}
return null;
})
.filter(Objects::nonNull);

但是恕我直言,这真的很难看。

最佳答案

模式匹配+mapMulti

要将父类(super class)型的 Stream 强制为其子类型之一的 Stream,您可以使用 Pattern matching for 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);
});

模式匹配+flatMap

要为 instanceof 使用模式匹配,您还可以使用经典的流操作 flatMap(),这就像 mapMulti() 是为了执行 one-对多转换。

两者之间的重要区别是 mapMulti() 通过其 Consumer零个或多个 元素替换初始流元素,同时flatMap() 需要生成一个新的 Stream 来展平数据。在这种情况下,使用 mapMulti() 会更有优势,因为如果列表很大,则为每个元素生成单例流可能成本很高。

Stream<Zebra> zebraStream = animalStream
.flatMap(animal ->
animal instanceof Zebra zebra ? Stream.of(zebra) : null
);

注意,根据documentation除了空流,我们还可以返回 null(这很方便,因为 Stream.empty() 不返回常量但生成了一个新对象):

If a mapped stream is null an empty stream is used, instead.

关于java - 在 Stream 中为 Instanceof 应用模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74416190/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com