2013-10-22 10 views
25

जेडीके 8 ईए अब बाहर है, और मैं सिर्फ लैम्ब्डा और नए स्ट्रीम एपीआई में उपयोग करने की कोशिश कर रहा हूं। मैं समानांतर धारा के साथ एक सूची को सॉर्ट करने की कोशिश की है, लेकिन परिणाम हमेशा गलत है:जावा 8 समांतरस्ट्रीम() सॉर्ट किए गए()

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 
    } 
} 

उत्पादन:

C 
F 
B 
H 
A 

नोट है कि हर बार उत्पादन अलग है। मेरे सवाल है, क्या यह एक बग है? या समानांतर में एक सूची को सॉर्ट करना संभव नहीं है? यदि हां, तो जावाडॉक यह क्यों नहीं बताता है? आखिरी सवाल, क्या कोई अन्य ऑपरेशन है जिसका उत्पादन धारा प्रकार के आधार पर भिन्न होगा?

+1

सॉर्टिंग के बाद डुप्लीकेट को हटाने के लिए शायद बेहतर होगा। – Ingo

उत्तर

44

आपको forEachOrdered का उपयोग करने की आवश्यकता है, forEach नहीं।

प्रति forEach दस्तावेज़ के रूप में:

समानांतर धारा पाइपलाइनों के लिए, इस आपरेशन, धारा के मुठभेड़ आदेश का सम्मान करने के रूप में ऐसा करने समानांतरवाद के लाभ के बलिदान करेंगे गारंटी नहीं है। किसी दिए गए तत्व के लिए, कार्रवाई किसी भी समय और पुस्तकालय चुनने वाले किसी भी थ्रेड में किया जा सकता है। यदि कार्रवाई साझा स्थिति तक पहुंच जाती है, तो यह आवश्यक सिंक्रनाइज़ेशन प्रदान करने के लिए ज़िम्मेदार है।

+1

+1 शानदार! यह वही है जिसे मैं देख रहा था। –

+0

मेरा अनुमान है कि आंतरिक रूप से यह एक "क्रमबद्ध" सूची बना रहा है, प्रत्येक थ्रेड उस सूची में जोड़ता है, फिर प्रवाह में अगले चरण तक चलता है (इसके लिए) ताकि यह आदेश से बाहर हो जाए, FWIW। – rogerdpack

6

इसके अतिरिक्त, आप समांतरता के बारे में और here से बहुत अच्छे उदाहरण के साथ पढ़ सकते हैं। संक्षेप में, समानांतर धारा में प्रत्येक के लिए उपयोग करने से परिणामस्वरूप समानांतरता के लाभ कम हो सकते हैं।

यहाँ एक ही संसाधन से उदाहरण:

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

यह थोड़ा पतला है। कृपया इसे संपादित करके अपने उत्तर पर विस्तार करें। –

संबंधित मुद्दे