是否可以分阶段在流上执行映射而不创建中间集合?
我正在使用Selenium并映射WebElement
s的流。分批执行这些操作非常重要,以避免因为页面动态更新自身而引发StaleReferenceException
,并且某些map
操作需要相对较长的时间才能完成。
问题(简化):
public class StreamTest {
public static void main(String[] args) {
String[] input = new String[] {"1", "2", "3", "4", "5"};
List<String> list = map(input).collect(Collectors.toList());
}
private static Stream<String> map(String[] input) {
return Arrays.stream(input).parallel()
.map(s -> {
String ret = s + "0";
System.out.println(String.format("%10s%10s", s, ret));
return ret;
})
.map(s -> {
String ret = s + "0";
System.out.println(String.format("%10s%10s", s, ret));
return ret;
})
.map(s -> {
String ret = s + "0";
System.out.println(String.format("%10s%10s", s, ret));
return ret;
});
}
}
示例输出:
3 30
4 40
30 300
1 10
5 50
10 100
2 20
50 500
300 3000
40 400
500 5000
20 200
100 1000
400 4000
200 2000
期望的输出:
1 10
2 20
3 30
4 40
5 50
10 100
20 200
30 300
40 400
50 500
100 1000
200 2000
300 3000
400 4000
500 5000
当前解决方案:
private static Stream<String> map(String[] input) {
return Arrays.stream(input)
.map(s -> s + "0")
.collect(Collectors.toList()).stream()
.map(s -> s + "0")
.collect(Collectors.toList()).stream()
.map(s -> s + "0");
}
有没有办法实现这一点,而不是在每次调用map
之间创建一个虚拟集合?
注意:我需要使用带有 n 调用map
的流而不是 n for循环的序列。
答案 0 :(得分:1)
这似乎有效:
String[] input = new String[] {"1", "2", "3", "4", "5"};
Stream.of("", "0", "00")
.flatMap(suffix -> Stream.of(input)
.map(prefix -> prefix + suffix)
.map(s -> String.format("%10s%10s", s, s + "0")))
.forEach(System.out::println);
错误的排序是由parallel()
调用引起的,这可能是可以避免的。
答案 1 :(得分:1)
这不是设计流的方式。
应用一系列地图操作而不创建中间集合,只有终端操作决定结果是什么(集合或单个值)。
但要批量工作(将第一个地图操作应用于所有输入,然后将第二个地图操作应用于所有第一个中间结果,依此类推),您需要中间集合。
答案 2 :(得分:0)
说实话,不知道你想做什么。这是符合您的样本输出的东西:
private static Stream<String> map(String[] input) {
return Stream.of("", "0", "00")
.flatMap(x -> Arrays.stream(input)
.map(y -> y + x)
.peek(z -> System.out.println(z + " " + z + "0"))
.map(z -> z + "0"))
.skip(2 * input.length);
}
您看到的无序结果是因为您使用parallel
而中间操作没有定义的执行顺序,只有终端执行此操作(除非另有说明 - 例如forEach
)