forEach 대 forEachOrdered in Java 8 Stream


87

이 방법은 실행 순서가 다르지만 모든 테스트에서 다른 순서 실행을 달성 할 수 없다는 것을 이해합니다.

예:

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

두 가지 방법이 다른 출력을 생성하는 경우 예를 제공하십시오.


병렬 스트림으로 시도하십시오.
— Pshemo 2015 년

@Pshemo는 가능한 옵션입니까?
— gstackoverflow 2015 년

5
지정되지 않은 주문은 "다른 주문이 보장됨"을 의미하지 않습니다. 그것은 단지 unspecified를 의미하며, 항상 조우 순서와 일치 할 가능성을 의미합니다. 내장 셔플 기능이 없습니다.
— Holger

답변:


90
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스트림이 순차적인지 병렬인지에 관계없이 소스에 지정된 순서대로 스트림의 요소를 처리합니다.

forEachJavadoc 에서 인용 :

이 작업의 동작은 명시 적으로 비 결정적입니다. 병렬 스트림 파이프 라인의 경우이 작업은 병렬 처리의 이점을 희생 할 수 있으므로 스트림의 발생 순서를 존중한다고 보장하지 않습니다.

forEachOrderedJavadoc이 다음과 같이 말할 때 (강조 표시) :

스트림에 정의 된 발생 순서가있는 경우 스트림의 발생 순서대로이 스트림의 각 요소에 대한 작업을 수행합니다 .


6
그래 네가 맞아. parallelStreams에서만 가능합니까?
— gstackoverflow 2015 년

6
지금 당장 병렬 스트림에만 적용되는 경우에도-그렇다고 말하는 것은 아닙니다. 일부 중간 단계가 정렬되지 않은 스트림을 활용하도록 최적화되는 경우 (예 : 정렬이 불안정한 알고리즘을 사용할 수있는 경우) 미래에 여전히 중단 될 수 있습니다. 스트림은 순서가 없습니다.
— the8472

1
따라서 ? forEachOrdered와 함께 사용 하는 것은 의미가 없습니다 parallel.
— Bhushan

3
@BhushanPatil 네, 맞습니다. stackoverflow.com/questions/47336825/…
— Sagar

1
forEachOrdered를 사용하면 순서별로 요소를 처리 한 다음 병렬 스트림을 사용하면 병렬 처리의 이점을 잃게됩니다. 제안 해주세요.
— 디팍

30

비록 forEach짧고 외모가 예뻐, 내가 사용하기에 좋을 것forEachOrdered 주문 사항이 명시 적으로이를 지정할 경우 모든 장소에서. 순차 스트림의 forEach경우 순서를 존중 하는 것 같고 의미 상 사용이 필요한 스트림 API 내부 코드 사용 forEach (순차적 인 것으로 알려진 스트림의 경우)까지 forEachOrdered! 그럼에도 불구하고 나중에 스트림을 병렬로 변경하기로 결정할 수 있으며 코드가 손상됩니다. 또한 forEachOrdered코드 리더 를 사용할 때 "순서가 중요합니다"라는 메시지가 표시됩니다. 따라서 코드를 더 잘 문서화합니다.

병렬 스트림의 forEach경우 비 결정적 순서로 실행될뿐만 아니라 다른 요소에 대해 다른 스레드에서 동시에 실행되도록 할 수도 있습니다 (에서는 가능하지 않음 forEachOrdered).

마지막으로 forEach/ 둘 다 forEachOrdered거의 유용하지 않습니다. 대부분의 경우에 당신은 실제로 이렇게 작업처럼,뿐만 아니라 부작용을 몇 가지 결과를 생성 할 필요가 reduce또는 collect더 적합해야한다. 자연에 의한 축소 작업을 통해 표현하는 forEach것은 일반적으로 나쁜 스타일로 간주됩니다.


7
"마지막으로 forEach / forEachOrdered 둘 다 거의 유용하지 않습니다." 전 그렇게 생각하지 않아요. 이러한 방법이 과도하게 사용 된 것 같습니다.
— Tunaki

대답 해줘서 고마워요. 그러나 그것은 실제 생활의 예가 아닙니다. 난 그냥 자바 8 배울
— gstackoverflow

왜 forEachOrdered그 코드에서 사용하는 것이 의미 상 필요 합니까?
— RealSkeptic

1
@RealSkeptic, 사용자 지정 스트림입니다 (으로 전달됨 flatMap). 순서를 지정할 수 있으므로 동일한 순서로 결과 스트림에 배치해야합니다.
— Tagir Valeev 2015

2
@RealSkeptic, 당신은 진짜 회의론자입니다! Stream.of("a", "b", "c").flatMap(s -> Stream.of("1", "2", "3").map(s::concat)).spliterator().hasCharacteristics(Spliterator.ORDERED)true를 반환하므로 결과 스트림의 순서를 결정해야합니다. JDK 문서에서 이에 대해 명시 적으로 언급해야한다고 생각되면 자유롭게 버그를 제출하십시오.
— Tagir Valeev 2015

15

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 without using parallel****

sushil mittal

****forEach with using parallel****

mihul issltat

****forEachOrdered with using parallel****

sushil mittal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.