forEach vs forEachOrdered в потоке Java 8

Я понимаю, что эти методы отличаются порядком выполнения, но во всем моем тесте я не могу добиться выполнения другого порядка.

пример:

System.out.println("forEach Demo");
Stream.of("AAA","BBB","CCC").forEach(s->System.out.println("Output:"+s));
System.out.println("forEachOrdered Demo");
Stream.of("AAA","BBB","CCC").forEachOrdered(s->System.out.println("Output:"+s));

выход:

forEach Demo
Output:AAA
Output:BBB
Output:CCC
forEachOrdered Demo
Output:AAA
Output:BBB
Output:CCC

пожалуйста, приведите примеры, когда 2 методы дают различные результаты.

3 ответов


Stream.of("AAA","BBB","CCC").parallel().forEach(s->System.out.println("Output:"+s));
Stream.of("AAA","BBB","CCC").parallel().forEachOrdered(s->System.out.println("Output:"+s));

вторая строка всегда выводит

Output:AAA
Output:BBB
Output:CCC

в то время как первый не гарантируется, так как заказ не сохраняется. forEachOrdered будет обрабатывать элементы потока в порядке, указанном его источником, независимо от того, является ли поток последовательным или параллельным.

цитирую forEach Javadoc:

поведение этой операции явно недетерминированные. Для параллельных трубопроводов потока, это операция не гарантирует уважения порядка встречи потока, так как это принесло бы в жертву преимущество параллелизма.

когда forEachOrdered Javadoc состояния (акцент мой):

выполнить действие для каждого элемента этого потока, в порядке встречи потока если поток имеет определенный порядок встречи.


хотя forEach короче и выглядит красивее, я бы посоветовал использовать forEachOrdered в каждом месте, где порядок имеет значение, чтобы явно указать это. Для последовательных потоков forEach кажется, уважает порядок и даже поток внутреннего кода API использует forEach (для потока, который, как известно, является последовательным), где семантически необходимо использовать forEachOrdered! Тем не менее позже вы можете изменить свой поток на параллельный, и ваш код будет нарушен. Также при использовании forEachOrdered читатель Вашего кода видит сообщение:"порядок имеет значение здесь". Таким образом, он документирует ваш код лучше.

Обратите также внимание, что для параллельных потоков forEach не только выполняется в недетерминированном порядке, но вы также можете выполнить его одновременно в разных потоках для разных элементов (что невозможно с forEachOrdered).

наконец-то оба forEach/forEachOrdered редко полезно. В большинстве случаев вам действительно нужно получить какой-то результат, а не только побочный эффект, таким образом операции, как reduce или collect должен быть более подходящим. Выражая операцию уменьшения по своей природе через forEach обычно считается плохим стилем.


forEach () метод выполняет действие для каждого элемента этого потока. Для параллельного потока эта операция не гарантирует поддержание порядка потока.

forEachOrdered() метод выполняет действие для каждого элемента этого потока, гарантируя, что каждый элемент обрабатывается в порядке возникнут потоки, которые имеют определенный порядок встречи.

бери ниже пример:

    String str = "sushil mittal";
    System.out.println("****forEach without using parallel****");
    str.chars().forEach(s -> System.out.print((char) s));
    System.out.println("\n****forEach with using parallel****");

    str.chars().parallel().forEach(s -> System.out.print((char) s));
    System.out.println("\n****forEachOrdered with using parallel****");

    str.chars().parallel().forEachOrdered(s -> System.out.print((char) s));

выход:

* * * * forEach без использования parallel****

сушил Миттал

* * * * forEach с использованием parallel****

mihul issltat

* * * * forEachOrdered с использованием параллельного****

сушил Миттал