चालान की एक श्रृंखला श्रृंखला और इंटरमीडिएट रिटर्न मूल्यों को संग्रहीत करने वाले आमंत्रणों की एक श्रृंखला के बीच कोई अर्थपूर्ण अंतर नहीं है। इस प्रकार, निम्नलिखित कोड के टुकड़े के बराबर हैं:
a = object.foo();
b = a.bar();
c = b.baz();
और
c = object.foo().bar().baz();
या तो मामले में, प्रत्येक विधि पिछले मंगलाचरण के परिणाम पर शुरू हो जाती है। लेकिन बाद के मामले में, मध्यवर्ती परिणाम संग्रहीत नहीं किए जाते हैं लेकिन अगले आमंत्रण पर खो जाते हैं। स्ट्रीम एपीआई के मामले में, इंटरमीडिएट परिणाम का उपयोग नहीं किया जाना चाहिए, इसके बाद आप अगली विधि कहलाएंगे, इस प्रकार चेनिंग स्ट्रीम का उपयोग करने का प्राकृतिक तरीका है क्योंकि यह आंतरिक रूप से सुनिश्चित करता है कि आप एक से अधिक तरीकों का आह्वान नहीं करते हैं एक लौटा संदर्भ पर।
फिर भी, एक स्ट्रीम के संदर्भ को तब तक स्टोर करना गलत नहीं है जब तक आप एक बार से अधिक संदर्भित संदर्भ का उपयोग न करने के अनुबंध का पालन करते हैं। इसका उपयोग करके वे आपके प्रश्न के अनुसार, यानी अगले आमंत्रण के परिणामस्वरूप चर को ओवरराइट कर रहे हैं, आप यह भी सुनिश्चित करते हैं कि आप एक लौटा संदर्भ पर एक से अधिक विधि का आह्वान नहीं करते हैं, इस प्रकार, यह एक सही उपयोग है।बेशक, यह केवल उसी प्रकार के मध्यवर्ती परिणामों के साथ काम करता है, इसलिए जब आप map
या flatMap
का उपयोग कर रहे हैं, तो एक अलग संदर्भ प्रकार की स्ट्रीम प्राप्त करने के बाद, आप स्थानीय चर को ओवरराइट नहीं कर सकते हैं। फिर आपको पुराने स्थानीय चर का फिर से उपयोग करने के लिए सावधान रहना होगा, लेकिन जैसा कि कहा गया है, जब तक आप अगले आमंत्रण के बाद इसका उपयोग नहीं कर रहे हैं, मध्यवर्ती भंडारण में कुछ भी गलत नहीं है।
कभी-कभी, में स्टोर करने के लिए, उदा।
try(Stream<String> stream = Files.lines(Paths.get("myFile.txt"))) {
stream.filter(s -> !s.isEmpty()).forEach(System.out::println);
}
ध्यान दें कि कोड निम्न विकल्पों के बराबर है:
try(Stream<String> stream = Files.lines(Paths.get("myFile.txt")).filter(s->!s.isEmpty())) {
stream.forEach(System.out::println);
}
और
try(Stream<String> srcStream = Files.lines(Paths.get("myFile.txt"))) {
Stream<String> tmp = srcStream.filter(s -> !s.isEmpty());
// must not be use variable srcStream here:
tmp.forEach(System.out::println);
}
वे बराबर हैं क्योंकि forEach
हमेशा filter
का परिणाम जो हमेशा शुरू हो जाती है पर शुरू हो जाती है Files.lines
के परिणामस्वरूप और इससे कोई फर्क नहीं पड़ता कि अंतिम close()
ऑपरेशन का आह्वान किया गया है डी बंद होने से पूरी स्ट्रीम पाइपलाइन प्रभावित होती है।
इसे एक वाक्य में रखने के लिए, जिस तरह से आप इसका उपयोग करते हैं, वह सही है।
मैं भी पसंद करते हैं इसे उस तरह से करने के लिए, के रूप में एक limit
आपरेशन चेनिंग नहीं है जब आप लागू करने के लिए एक सीमा अपने इरादे अभिव्यक्ति की स्पष्ट तरीका है नहीं करना चाहती। यह भी ध्यान देने योग्य बात है कि सुझाव दिया विकल्प मामलों का एक बहुत में काम कर सकते हैं लायक है, लेकिन वे नहीं शब्दार्थ बराबर हैं:
.limit(condition? aLimit: Long.MAX_VALUE)
मानता है कि तत्वों की अधिकतम संख्या, क्या आपने कभी सामना कर सकते हैं, Long.MAX_VALUE
लेकिन धाराओं कर सकते हैं उससे अधिक तत्व हैं, वे अनंत भी हो सकते हैं।
.limit(condition? aLimit: list.size())
जब स्ट्रीम स्रोत list
, एक धारा के आलसी मूल्यांकन टूट रहा है। सिद्धांत रूप में, टर्मिनल एक्शन शुरू होने पर एक म्यूटेबल स्ट्रीम स्रोत कानूनी रूप से उस बिंदु तक मनमाने ढंग से बदल सकता है। नतीजा इस बिंदु तक किए गए सभी संशोधनों को प्रतिबिंबित करेगा। जब आप list.size()
को शामिल करने वाले मध्यवर्ती ऑपरेशन को जोड़ते हैं, यानी इस बिंदु पर सूची का वास्तविक आकार, इस बिंदु और टर्मिनल ऑपरेशन के बीच संग्रह पर लागू किए गए संशोधनों में इस मान को "वास्तव में कोई सीमा" के मुकाबले अलग अर्थ नहीं हो सकता है अर्थ।
“Non Interference” section of the API documentation साथ तुलना करें:
अच्छी तरह से व्यवहार धारा स्रोतों के लिए, इससे पहले कि टर्मिनल आपरेशन शुरू स्रोत संशोधित किया जा सकता है और उन संशोधनों कवर तत्वों में परिलक्षित होगा। उदाहरण के लिए, निम्नलिखित कोड पर विचार करें:
List<String> l = new ArrayList(Arrays.asList("one", "two"));
Stream<String> sl = l.stream();
l.add("three");
String s = sl.collect(joining(" "));
सबसे पहले एक सूची दो तारों से बना है: "एक"; और दो"। फिर उस सूची से एक धारा बनाई गई है। अगला सूची तीसरी स्ट्रिंग जोड़कर संशोधित की जाती है: "तीन"। अंत में धारा के तत्व एकत्र किए जाते हैं और एक साथ जुड़ जाते हैं। चूंकि टर्मिनल संग्रह ऑपरेशन शुरू होने से पहले सूची संशोधित की गई थी, परिणाम "एक दो तीन" की एक स्ट्रिंग होगी।
बेशक, यह सामान्य रूप से एक दुर्लभ कोने का मामला है, एक प्रोग्रामर स्रोत स्ट्रीम संग्रह को संशोधित किए बिना एक संपूर्ण स्ट्रीम पाइपलाइन तैयार करेगा। फिर भी, विभिन्न अर्थपूर्ण अवशेष हैं और जब आप एक बार कोने के मामले में प्रवेश करते हैं तो यह बग खोजने में बहुत मुश्किल हो सकता है।
आगे, चूंकि वे समकक्ष नहीं हैं, इसलिए स्ट्रीम एपीआई इन मानों को "वास्तव में कोई सीमा" के रूप में कभी नहीं पहचान पाएगी। यहां तक कि Long.MAX_VALUE
निर्दिष्ट करने का भी अर्थ है कि धारा कार्यान्वयन को सुनिश्चित करने के लिए संसाधित तत्वों की संख्या को ट्रैक करना है कि सीमा का पालन किया गया है। इस प्रकार, limit
ऑपरेशन को जोड़ने से एक संख्या को सीमित करने पर एक महत्वपूर्ण प्रदर्शन लाभ हो सकता है जिसे प्रोग्रामर कभी पार नहीं होने की अपेक्षा करता है।
ऐसा लगता है कि आप 'stream.filter()' के आउटपुट को कैप्चर नहीं कर रहे हैं। – whaleberg
यदि आप इसे एक पंक्ति में लिखना चाहते हैं, तो आप '.limit (सीमा! = -1? सीमा: Long.MAX_VALUE) लिख सकते हैं, लेकिन मैं नहीं करूँगा। – zapl
@whaleberg, @WillShackleford, @ पीटर: मेरी गलती, मैं फ़िल्टर किए गए स्ट्रीम के मान को अपने मूल उदाहरण कोड में 'स्ट्रीम' पर असाइन करना भूल गया। मुझे लगता है कि मैं गलत तरीके से धाराओं को समझ गया। मैंने पढ़ा है कि सभी धाराओं को टर्मिनल ऑपरेशन के बाद निष्पादित किया जाना चाहिए ताकि उन्हें निष्पादित किया जा सके, इसलिए मैंने सोचा कि परिणामी धारा को उसी 'स्ट्रीम' चर में स्टोर करना गलत था। मैं अपना मूल प्रश्न अपडेट करूंगा। – Lani