Порядок обработки списка потоков Java

Может кто-нибудь объяснить вывод приведенного ниже кода потоков Java:

List<Integer> l = new ArrayList<>();
l.add(0);
l.add(1);
l.add(2);
l.add(3);
l.add(4);
l.add(4);
l.stream()
    .distinct()
    .map(v -> {
        System.out.println("In Map " + v);
        return v;
    }).forEach(v -> {
        System.out.println("In ForEach " + v);
    });

Я ожидал:

In Map 0 
    In Map 1 
    In Map 2 
    In Map 3 
    In Map 4 
    In ForEach 0 
    In ForEach 1 
    In ForEach 2 
    In ForEach 3 
    In ForEach 4

Но печатает:

In Map 0 
    In ForEach 0 
    In Map 1 
    In ForEach 1 
    In Map 2 
    In ForEach 2 
    In Map 3 
    In ForEach 3 
    In Map 4 
    In ForEach 4

Есть ли причина, по которой вы так ожидали?

pvpkiran 30.05.2018 14:37

Потоки - это ленивый, из источника извлекается по одному элементу, то, что вы видите, ожидаемо. Я на 100% уверен, что это дубликат ...

Eugene 30.05.2018 14:37
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
75
2

Ответы 2

Я думаю, это довольно очевидно :) Это идет в Map, и для каждого значения выполняется вызов foreach. Это как вложенные циклы. Получите значение 1 - обработайте, получите значение 2 обработайте;) И вот что вы получите

Конвейер Stream оценивается лениво. Это означает, что он выполняет промежуточные операции с элементами Stream только тогда, когда такие элементы требуются для работы терминала - forEach в вашем случае.

Если для работы терминала требуется только один элемент (например, findFirst()), операция map() будет выполняться только для первого элемента Stream.

Другие вопросы по теме