Java 8 Streams:分阶段映射

时间:2018-05-08 19:53:04

标签: selenium java-8 java-stream

是否可以分阶段在流上执行映射而不创建中间集合?

我正在使用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循环的序列。

3 个答案:

答案 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

相关问题