如果我执行以下代码将两个流“连接”起来:
- 首先使用 flatMap 对
Stream<Stream<Integer>>
进行操作 - 然后使用
Stream.concat()
缩减一个Stream<Stream<Integer>>
public class FlatMapVsReduce {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
Predicate<Integer> predicate1 = i -> {
System.out.println("testing first condition with " + i);
return i == 3;
};
Predicate<Integer> predicate2 = i -> {
System.out.println("testing second condition with " + i);
return i == 7;
};
System.out.println("Testing with flatMap");
Integer result1 =
Stream.of(list.stream().filter(predicate1),
list.stream().filter(predicate2))
.flatMap(Function.identity())
.peek(i -> System.out.println("peeking " + i))
.findFirst()
.orElse(null);
System.out.println("result1 = " + result1);
System.out.println();
System.out.println("Testing with reduce");
Integer result2 =
Stream.of(list.stream().filter(predicate1),
list.stream().filter(predicate2))
.reduce(Stream::concat)
.orElseGet(Stream::empty)
.peek(i -> System.out.println("peeking " + i))
.findFirst()
.orElse(null);
System.out.println("result2 = " + result2);
}
}
在这两种情况下,我都得到了预期的结果(3)。然而,第一次操作将第一个过滤器应用于集合中的每个元素,而第二次操作则会在遇到一个元素后停止。输出结果为:
Testing with flatMap
testing first condition with 1
testing first condition with 2
testing first condition with 3
peeking 3
testing first condition with 4
testing first condition with 5
testing first condition with 6
testing first condition with 7
testing first condition with 8
testing first condition with 9
result1 = 3
Testing with reduce
testing first condition with 1
testing first condition with 2
testing first condition with 3
peeking 3
result2 = 3
为什么这两种情况的行为会有差异?JDK代码是否可以改进,使得第一种情况与第二种情况一样高效,或者是flatMap中的某些因素使其不可能实现?
补充说明:以下替代方案与使用reduce的方案一样有效,但我仍然无法解释原因:
Integer result3 = Stream.of(predicate1, predicate2)
.flatMap(c -> list.stream().filter(c).limit(1))
.peek(i -> System.out.println("peeking " + i))
.findFirst()
.orElse(null);
System.out.println("result3 = " + result3);
flatMap
调用forEach
来完全消耗每个子流,出于某种原因。我在浏览代码方面很糟糕,所以我不确定它为什么这样做,或者我是否正确阅读了它。 - user2357112flatmap
是可能的... - Holger