2013-10-22 2 views
25

JDK 8 EA가 출시되었습니다. 이제 막 lambda와 새로운 Stream API에 익숙해졌습니다. 나는 병렬 스트림 목록을 정렬 시도했지만, 결과는 항상 잘못 :java 8 parallelStream() with sorted()

import java.util.ArrayList; 
import java.util.List; 

public class Test 
{ 
    public static void main(String[] args) 
    { 
     List<String> list = new ArrayList<>(); 
     list.add("C"); 
     list.add("H"); 
     list.add("A"); 
     list.add("A"); 
     list.add("B"); 
     list.add("F"); 
     list.add(""); 

     list.parallelStream() // in parallel, not just concurrently! 
      .filter(s -> !s.isEmpty()) // remove empty strings 
      .distinct() // remove duplicates 
      .sorted() // sort them 
      .forEach(s -> System.out.println(s)); // print each item 
    } 
} 

OUTPUT : 출력이 다른 때마다 것을

C 
F 
B 
H 
A 

참고. 제 질문은 버그입니까? 또는 목록을 병렬로 정렬 할 수 없습니까? 그렇다면 JavaDoc이 그 이유를 설명하지 않는 이유는 무엇입니까? 마지막 질문, 출력이 스트림 유형에 따라 다른 조작이 있습니까?

+1

정렬 후 중복을 제거하는 것이 좋습니다. – Ingo

답변

44

forEachOrdered이 아닌 forEach을 사용해야합니다. forEach 문서 당으로

: 병렬 스트림 파이프 라인에 대한

이 작업은 이렇게하면 병렬의 이익을 희생하는 것처럼, 스트림의 만남 순서를 존중하고 보장하지 않습니다. 임의의 주어진 요소에 대해, 작업은 라이브러리가 선택한 모든 스레드에서 수행 될 수 있습니다. 활동이 공유 상태에 액세스하는 경우 필요한 동기화를 제공합니다.

+1

+1 화려한! 이것이 제가 찾고 있던 것입니다. –

+0

내 생각 엔 내부적으로 "정렬 된"목록을 만들고, 각 스레드가 해당 목록에 추가 한 다음 흐름 (forEach)의 다음 단계로 진행하여 FWIW 순서로 실행합니다. – rogerdpack

6

또한 here에서 아주 좋은 예와 병렬 및 forEachOrdered에 대한 자세한 내용을보실 수 있습니다. 요약하면 병렬 스트림에서 forEachOrdered를 사용하면 병렬 처리의 이점을 잃을 수 있습니다. 여기

동일한 자원에서 예

:

Integer[] intArray = {1, 2, 3, 4, 5, 6, 7, 8 }; 
List<Integer> listOfIntegers = 
    new ArrayList<>(Arrays.asList(intArray)); 

System.out.println("listOfIntegers:"); 
listOfIntegers 
    .stream() 
    .forEach(e -> System.out.print(e + " ")); 
System.out.println(""); 

System.out.println("listOfIntegers sorted in reverse order:"); 
Comparator<Integer> normal = Integer::compare; 
Comparator<Integer> reversed = normal.reversed(); 
Collections.sort(listOfIntegers, reversed); 
listOfIntegers 
    .stream() 
    .forEach(e -> System.out.print(e + " ")); 
System.out.println(""); 

System.out.println("Parallel stream"); 
listOfIntegers 
    .parallelStream() 
    .forEach(e -> System.out.print(e + " ")); 
System.out.println(""); 

System.out.println("Another parallel stream:"); 
listOfIntegers 
    .parallelStream() 
    .forEach(e -> System.out.print(e + " ")); 
System.out.println(""); 

System.out.println("With forEachOrdered:"); 
listOfIntegers 
    .parallelStream() 
    .forEachOrdered(e -> System.out.print(e + " ")); 
System.out.println(""); 

출력 다섯 번째 파이프 라인은 상기 스트림의 요소를 처리하는 방법 forEachOrdered를 사용

listOfIntegers: 
1 2 3 4 5 6 7 8 
listOfIntegers sorted in reverse order: 
8 7 6 5 4 3 2 1 
Parallel stream: 
3 4 1 6 2 5 7 8 
Another parallel stream: 
6 3 1 5 7 8 4 2 
With forEachOrdered: 
8 7 6 5 4 3 2 1 

인 스트림을 직렬 또는 병렬로 실행했는지 여부와 상관없이 해당 소스로 지정된 순서 . 병렬 스트림

와 forEachOrdered 같은 작업을 사용하는 경우 병렬 처리의 이점을 잃을 수 있습니다 참고.

+0

그건 좀 가늘다. 답변을 편집하여 확장하십시오. –