जावा 8 स्ट्रीम में forEachOrdered


86

मैं समझता हूं कि ये विधियां क्रियान्वयन के क्रम में भिन्न हैं लेकिन मेरे सभी परीक्षण में मैं अलग-अलग क्रम निष्पादन प्राप्त नहीं कर सकता।

उदाहरण:

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 तरीके अलग-अलग आउटपुट उत्पन्न करेंगे।


शायद समानांतर धाराओं के साथ प्रयास करें।
Pshemo

@Phemo क्या यह केवल संभव विकल्प है?
13

5
अनिर्दिष्ट आदेश का अर्थ "भिन्न आदेश होने की गारंटी" नहीं है। इसका मतलब सिर्फ अनिर्दिष्ट है , जो हमेशा मुठभेड़ क्रम से मेल खाने की संभावना को दर्शाता है। कोई अंतर्निर्मित फेरबदल फ़ंक्शन नहीं है।
होल्गर

जवाबों:


89
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:

इस ऑपरेशन का व्यवहार स्पष्ट रूप से अप्रकट है। समानांतर स्ट्रीम पाइपलाइनों के लिए, यह ऑपरेशन स्ट्रीम के एनकाउंटर ऑर्डर का सम्मान करने की गारंटी नहीं देता है, क्योंकि ऐसा करने से समानता का लाभ मिलता है।

जब forEachOrderedजावदोक कहता है (मेरा जोर):

इस स्ट्रीम के प्रत्येक तत्व के लिए एक एक्शन करता है, तो स्ट्रीम के एनकाउंटर ऑर्डर में अगर स्ट्रीम में एनकाउंटर ऑर्डर होता है।


6
हाँ आप सही है। क्या यह केवल समांतर तारों के लिए संभव है?
gstackoverflow

6
यहां तक ​​कि अगर यह केवल समानांतर धाराओं पर लागू होगा - और मैं यह नहीं कह रहा हूं - यह अभी भी भविष्य में टूट सकता है अगर कुछ मध्यवर्ती कदम अनियंत्रित धाराओं का लाभ लेने के लिए अनुकूलित हो जाते हैं, जैसे कि एक सॉर्ट एक अस्थिर एल्गोरिदम का उपयोग कर सकता है यदि धारा अनियंत्रित है।
the8472

1
तो यह उपयोग करने के लिए कोई मतलब नहीं है forEachOrderedके साथ parallel?
भूषण

3
@ भूषणपटील हां, यह सही है। stackoverflow.com/questions/47336825/…
सागर

1
ForEachOrdered का उपयोग करके तत्व को संसाधित करेगा, फिर समानांतर धाराओं का उपयोग करके समानता का लाभ कम कर देगा। कृपया सुझाव दे।
दीपक

30

हालांकि forEachछोटा और प्रीतिकर लगता है, मैं forEachOrderedहर उस जगह पर उपयोग करने का सुझाव दूंगा जहां ऑर्डर स्पष्ट रूप से यह निर्दिष्ट करता है। अनुक्रमिक धाराओं के forEachलिए ऑर्डर का सम्मान करना प्रतीत होता है और यहां तक ​​कि एपीआई आंतरिक कोड का उपयोग करता है forEach (स्ट्रीम के लिए जिसे अनुक्रमिक कहा जाता है) जहां यह उपयोग करने के लिए शब्दशः आवश्यक है forEachOrdered! फिर भी आप बाद में अपनी धारा को समानांतर बदलने का फैसला कर सकते हैं और आपका कोड टूट जाएगा। जब आप forEachOrderedअपने कोड के पाठक का उपयोग करते हैं तब भी संदेश देखते हैं: "यहां आदेश मायने रखता है"। इस प्रकार यह आपके कोड को बेहतर तरीके से दस्तावेजित करता है।

ध्यान दें कि समानांतर धाराओं के लिए forEachन केवल गैर-नियतात्मक क्रम में निष्पादित किया जाता है, लेकिन आप इसे अलग-अलग तत्वों के लिए अलग-अलग थ्रेड्स में एक साथ निष्पादित भी कर सकते हैं (जो कि संभव नहीं है forEachOrdered)।

अंत में दोनों forEach/ forEachOrderedशायद ही कभी उपयोगी होते हैं। अधिकांश मामलों में आपको वास्तव में कुछ परिणाम उत्पन्न करने की आवश्यकता होती है, न कि केवल साइड-इफ़ेक्ट, इस प्रकार संचालन reduceया collectअधिक उपयुक्त होना चाहिए। के माध्यम से कम करने वाली प्रकृति के संचालन को व्यक्त करना forEachआमतौर पर एक बुरा शैली माना जाता है।


7
"अंत में दोनों forEach / forEachOrdered शायद ही कभी उपयोगी होते हैं"। मैं ज्यादा सहमत नहीं हो सकती। ऐसा लगता है कि ये विधियां अति-उपयोग में हैं।
तुनकी

उत्तर के लिए धन्यवाद। लेकिन यह वास्तविक जीवन उदाहरण नहीं है। मैं सिर्फ जावा 8 सीखता हूं
gstackoverflow

forEachOrderedउस कोड में उपयोग करना क्यों आवश्यक है ?
रियल सेप्टिक

1
@ रेलेस्केप्टिक, यह उपयोगकर्ता द्वारा निर्दिष्ट स्ट्रीम (में पारित flatMap) है। यह आदेश दिया जा सकता है, इसलिए इसे उसी क्रम में परिणामी धारा में रखा जाना चाहिए।
टैगिर वलेव

2
@RealSkeptic, आप असली उलझन में हैं! Stream.of("a", "b", "c").flatMap(s -> Stream.of("1", "2", "3").map(s::concat)).spliterator().hasCharacteristics(Spliterator.ORDERED)यह सच है, इस प्रकार परिणामी धारा के लिए आदेश निर्धारित किया जाना चाहिए। यदि आपको लगता है कि JDK प्रलेखन को स्पष्ट रूप से इस बारे में कहना चाहिए, तो बग को सबमिट करने के लिए स्वतंत्र महसूस करें।
टैगिर वलेव

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.