जावा 8 धाराओं में प्रसंस्करण का क्रम कैसे सुनिश्चित करें?


148

मैं एक XMLजावा ऑब्जेक्ट के अंदर सूचियों को प्रोसेस करना चाहता हूं । मुझे सभी तत्वों को संसाधित करना सुनिश्चित करना है, ताकि मैं उन्हें प्राप्त कर सकूं।

इसलिए मुझे sequentialप्रत्येक streamउपयोग पर कॉल करना चाहिए ? list.stream().sequential().filter().forEach()

या जब तक मैं समानता का उपयोग नहीं करता तब तक धारा का उपयोग करना पर्याप्त है? list.stream().filter().forEach()

जवाबों:


338

आप गलत सवाल पूछ रहे हैं। आप के बारे में पूछ रहे हैं sequentialबनाम parallelजबकि आप इस प्रक्रिया के आइटम करना चाहते हैं क्रम में है, तो आप के बारे में पूछने के लिए आदेश देने की । यदि आपके पास एक ऑर्डर की गई स्ट्रीम है और ऑपरेशन करते हैं जो ऑर्डर को बनाए रखने की गारंटी देते हैं, तो इससे कोई फर्क नहीं पड़ता कि स्ट्रीम समानांतर या अनुक्रमिक में संसाधित है या नहीं; कार्यान्वयन आदेश को बनाए रखेगा।

आदेशित संपत्ति समानांतर बनाम अनुक्रमिक से अलग है। उदाहरण के लिए, यदि आप स्ट्रीम stream()पर कॉल HashSetकरते हैं, तो एक ऑर्डर की गई रिटर्न stream()पर कॉल करते समय अनियंत्रित हो जाएगा List। ध्यान दें कि आप unordered()ऑर्डर देने वाले अनुबंध को जारी करने और संभावित रूप से प्रदर्शन बढ़ाने के लिए कॉल कर सकते हैं । एक बार धारा के आदेश न होने के बाद आदेश को फिर से स्थापित करने का कोई तरीका नहीं है। (आदेश में एक अनियंत्रित धारा को चालू करने का एकमात्र तरीका कॉल करना है sorted, हालांकि, परिणामस्वरूप आदेश मूल आदेश नहीं है)।

पैकेज प्रलेखन के "ऑर्डरिंग" अनुभाग को भी देखें ।java.util.stream

पूरे स्ट्रीम ऑपरेशन के दौरान ऑर्डर के रखरखाव को सुनिश्चित करने के लिए, आपको स्ट्रीम के स्रोत, सभी मध्यवर्ती संचालन और टर्मिनल ऑपरेशन के दस्तावेज़ीकरण का अध्ययन करना होगा कि क्या वे ऑर्डर बनाए रखते हैं या नहीं (या स्रोत के पास पहले ऑर्डर है या नहीं जगह)।

यह बहुत ही सूक्ष्म जैसे हो सकता है, Stream.iterate(T,UnaryOperator)जबकि एक का आदेश दिया स्ट्रीम बनाता है Stream.generate(Supplier)एक बनाता है अव्यवस्थित धारा। ध्यान दें कि आपने अपने प्रश्न में एक सामान्य गलती भी की है क्योंकि आदेश को बनाए नहीं रखता है। यदि आप एक गारंटी क्रम में स्ट्रीम के तत्वों को संसाधित करना चाहते हैं तो आपको इसका उपयोग करना होगा।forEach forEachOrdered

तो अगर आपके listप्रश्न में वास्तव में एक है java.util.List, तो इसका stream()तरीका एक ऑर्डर की गई धारा लौटाएगा और filterऑर्डरिंग को नहीं बदलेगा। इसलिए यदि आप कॉल करते हैं list.stream().filter() .forEachOrdered(), तो सभी तत्वों को क्रमिक रूप से क्रम में संसाधित किया जाएगा, जबकि list.parallelStream().filter().forEachOrdered()तत्वों के लिए समानांतर (फ़िल्टर द्वारा) में संसाधित किया जा सकता है, लेकिन टर्मिनल कार्रवाई को अभी भी क्रम में कहा जाएगा (जो स्पष्ट रूप से समानांतर निष्पादन के लाभ को कम करेगा) ।

यदि आप, उदाहरण के लिए, जैसे एक ऑपरेशन का उपयोग करें

List<…> result=inputList.parallelStream().map(…).filter(…).collect(Collectors.toList());

संपूर्ण ऑपरेशन समानांतर निष्पादन से लाभान्वित हो सकता है लेकिन परिणामी सूची हमेशा सही क्रम में होगी, भले ही आप समानांतर या अनुक्रमिक धारा का उपयोग करें।


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

मैं समझता हूं List<>कि आदेश को संरक्षित करेगा, लेकिन करेगा Collection<>?
जोश सी।

5
@JoshC। यह वास्तविक संग्रह प्रकार पर निर्भर करता है। Setआमतौर पर नहीं है, जब तक कि यह एक SortedSetया नहीं है LinkedHashSet। एक का संग्रह देखा गया Map( keySet(), entrySet(), और values()इनहेरिट करती हैं) Mapकी नीति, यानी आदेश दिया जाता है जब नक्शा है एक SortedMapया LinkedHashMap। व्यवहार संग्रह के स्प्लिटर द्वारा सूचित विशेषताओं द्वारा निर्धारित किया जाता हैdefaultके कार्यान्वयन Collectionरिपोर्ट नहीं करता ORDEREDविशेषता, तो यह, अव्यवस्थित है, जब तक कि अधिरोहित।
होल्गर

@ होल्गर मेरा एक प्रश्न था जो आपके उत्तर के एक छोटे से खंड से संबंधित हो सकता है।
नमन

1
वर्थ नोटिंग जो forEachOrderedकेवल forEachसमानांतर धाराओं का उपयोग करते समय भिन्न होता है - लेकिन वैसे भी इसका उपयोग करने के लिए अच्छा अभ्यास तब होता है जब मामले में क्रमांकन के मामले में कभी भी बदलाव होता है ...
स्टीव चेम्बर्स

0

संक्षेप में:

आदेश स्रोत डेटा संरचना और मध्यवर्ती स्ट्रीम ऑपरेशन पर निर्भर करता है। यह मानते हुए कि आप एक Listप्रसंस्करण का उपयोग कर रहे हैं आदेश दिया जाना चाहिए (क्योंकि filterयहाँ अनुक्रम नहीं बदलेगा)।

अधिक जानकारी:

अनुक्रमिक बनाम समानांतर बनाम अनुक्रमित:

javadocs

S sequential()
Returns an equivalent stream that is sequential. May return itself, either because the stream was already sequential, or because the underlying stream state was modified to be sequential.
This is an intermediate operation.
S parallel()
Returns an equivalent stream that is parallel. May return itself, either because the stream was already parallel, or because the underlying stream state was modified to be parallel.
This is an intermediate operation.
S unordered()
Returns an equivalent stream that is unordered. May return itself, either because the stream was already unordered, or because the underlying stream state was modified to be unordered.
This is an intermediate operation.

स्ट्रीम ऑर्डरिंग:

javadocs

धाराएँ एक परिभाषित मुठभेड़ आदेश हो सकती हैं या नहीं। एक स्ट्रीम के पास एनकाउंटर ऑर्डर है या नहीं, यह स्रोत और मध्यवर्ती संचालन पर निर्भर करता है। कुछ धारा स्रोत (जैसे सूची या सरणियाँ) आंतरिक रूप से आदेशित होते हैं, जबकि अन्य (जैसे हैशसेट) नहीं होते हैं। कुछ मध्यवर्ती संचालन, जैसे कि सॉर्ट किए गए (), अन्यथा अनियंत्रित स्ट्रीम पर एक एनकाउंटर आदेश लागू कर सकते हैं, और अन्य एक ऑर्डर किए गए स्ट्रीम को अनस्टैंडर्ड, जैसे कि बेसस्ट्रीम.ऑनार्डेड () को रेंडर कर सकते हैं। इसके अलावा, कुछ टर्मिनल ऑपरेशन एनकाउंटर ऑर्डर को अनदेखा कर सकते हैं, जैसे कि forEach ()।

यदि एक धारा का आदेश दिया जाता है, तो अधिकांश ऑपरेशन उनके मुठभेड़ क्रम में तत्वों पर काम करने के लिए विवश होते हैं; यदि धारा का स्रोत [1, 2, 3] वाली सूची है, तो मानचित्र (एक्स -> x * 2) निष्पादित करने का परिणाम [2, 4, 6] होना चाहिए। हालांकि, अगर स्रोत में कोई परिभाषित आदेश नहीं है, तो मूल्यों का कोई भी क्रमचय [2, 4, 6] एक मान्य परिणाम होगा।

अनुक्रमिक धाराओं के लिए, मुठभेड़ आदेश की उपस्थिति या अनुपस्थिति प्रदर्शन को प्रभावित नहीं करती है, केवल नियतत्ववाद। यदि एक धारा का आदेश दिया जाता है, तो एक समान स्रोत पर समान स्ट्रीम पाइपलाइनों का बार-बार निष्पादन एक समान परिणाम उत्पन्न करेगा; यदि यह आदेश नहीं दिया गया है, तो बार-बार निष्पादन विभिन्न परिणाम उत्पन्न कर सकता है।

समानांतर धाराओं के लिए, ऑर्डर की कमी को शांत करना कभी-कभी अधिक कुशल निष्पादन को सक्षम कर सकता है। कुछ समग्र संचालन, जैसे कि फ़िल्टरिंग डुप्लिकेट (विशिष्ट ()) या समूहीकृत कटौती (कलेक्टर.ग्रुपिंगबी ()) को और अधिक कुशलता से लागू किया जा सकता है यदि तत्वों का क्रम प्रासंगिक नहीं है। इसी तरह, ऑपरेशन जो आंतरिक रूप से मुठभेड़ क्रम से बंधे होते हैं, जैसे कि सीमा (), समानता के लाभ को कम करते हुए, उचित क्रम सुनिश्चित करने के लिए बफरिंग की आवश्यकता हो सकती है। ऐसे मामलों में जहां स्ट्रीम में एनकाउंटर ऑर्डर होता है, लेकिन उपयोगकर्ता उस एनकाउंटर ऑर्डर के बारे में विशेष रूप से परवाह नहीं करता है, स्पष्ट रूप से अनऑर्डेड () के साथ स्ट्रीम को डी-ऑर्डर करने से कुछ स्टेटफुल या टर्मिनल ऑपरेशंस के समानांतर प्रदर्शन में सुधार हो सकता है। हालांकि, अधिकांश स्ट्रीम पाइपलाइन, जैसे "ब्लॉक के वजन का योग" उदाहरण ऊपर,

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