Java 8 Streams: карта поэтапно - PullRequest
0 голосов
/ 08 мая 2018

Возможно ли поэтапное сопоставление потока без создания промежуточных коллекций?

Я работаю с 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-loop.

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

Это похоже на работу:

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(), которого, вероятно, можно избежать.

0 голосов
/ 10 мая 2018

Это не то, как потоки были разработаны, чтобы вести себя.

Последовательность операций с картой применяется без создания промежуточных коллекций, только конечная операция решает, каким будет результат (коллекция или одно значение).

Но чтобы работать в пакетном режиме (применяя первую операцию карты ко всем входным данным, затем применяя вторую операцию карты ко всем первым промежуточным результатам и т. Д.), Вам нужны промежуточные коллекции.

0 голосов
/ 09 мая 2018

Если честно, понятия не имею, что ты пытаешься сделать. Вот что соответствует вашему примеру вывода:

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 например)

...