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.