हमें अशक्त मूल्यों के लिए jdk8 स्ट्रीम कैसे प्रबंधित करनी चाहिए


88

हैलो साथी जावा डेवलपर्स,

मुझे पता है कि विषय थोड़ा सा हो सकता है in advanceक्योंकि JDK8 अभी तक जारी नहीं किया गया है (और अब वैसे भी नहीं है ..) लेकिन मैं लैम्बडा के भावों और विशेष रूप से नए संग्रह एपीआई से संबंधित भाग के बारे में कुछ लेख पढ़ रहा था जिसे स्ट्रीम के रूप में जाना जाता है।

यहाँ उदाहरण के रूप में जावा पत्रिका लेख में दिया गया है (यह एक ओटर जनसंख्या एल्गोरिदम है ..):

Set<Otter> otters = getOtters();
System.out.println(otters.stream()
    .filter(o -> !o.isWild())
    .map(o -> o.getKeeper())
    .filter(k -> k.isFemale())
    .into(new ArrayList<>())
    .size());

मेरा प्रश्न यह है कि यदि सेट आंतरिक पुनरावृत्ति के मध्य में, ओटर में से एक शून्य है तो क्या होगा?

मैं एक NullPointerException को फेंकने की उम्मीद करूंगा लेकिन शायद मैं अभी भी पिछले विकास प्रतिमान (गैर-कार्यात्मक) में फंस गया हूं, क्या कोई मुझे बता सकता है कि इसे कैसे संभाला जाना चाहिए?

यदि यह वास्तव में एक NullPointerException को फेंक देता है, तो मुझे यह सुविधा काफी खतरनाक लगती है और इसे नीचे के रूप में ही उपयोग करना होगा:

  • यह सुनिश्चित करने के लिए डेवलपर कि कोई शून्य मान नहीं है (शायद पिछले .filter (o -> o! = Null) का उपयोग कर रहा है)
  • आवेदन सुनिश्चित करने के लिए डेवलपर शून्य ऊदबिलाव या एक विशेष NullOtter वस्तु से निपटने के लिए पैदा नहीं कर रहा है।

सबसे अच्छा विकल्प, या कोई अन्य विकल्प क्या है?

धन्यवाद!


3
मैं कहूंगा कि यह प्रोग्रामर के ऊपर है कि वह यहां सही काम करे; जेवीएम और कंपाइलर केवल इतना ही कर सकते हैं। ध्यान दें कि कुछ संग्रह कार्यान्वयन शून्य मानों की अनुमति नहीं देंगे।
fge

18
आप उपयोग कर सकते हैं filter(Objects::nonNull)के साथ Objectsसेjava.utils
Benj

जवाबों:


45

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

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

अशक्त के लिए सामान्य उपयोग मूल्य के अभाव को दर्शाता है। जावा एसई 8 के लिए प्रस्तावित इस से निपटने के लिए दृष्टिकोण एक नए java.util.Optionalप्रकार को पेश करना है , जो एक मूल्य की उपस्थिति / अनुपस्थिति को एन्क्रिप्ट करता है, साथ ही एक डिफ़ॉल्ट मूल्य की आपूर्ति करने, या एक अपवाद को फेंकने, या एक फ़ंक्शन को कॉल करने आदि के व्यवहार के साथ। मान अनुपस्थित है Optionalकेवल नए APIs द्वारा उपयोग किया जाता है, हालांकि, सिस्टम में बाकी सब कुछ अभी भी नल की संभावना के साथ रखा गया है।

मेरी सलाह है कि वास्तविक अशक्त संदर्भों को सबसे बड़ी सीमा तक टालें। यह देखने के लिए कि "null" ओटर कैसे हो सकता है, उदाहरण से देखना मुश्किल है। लेकिन यदि कोई आवश्यक था, तो ओपी के सुझाव शून्य मानों को फ़िल्टर करने या उन्हें एक प्रहरी वस्तु ( नल ऑब्जेक्ट पैटर्न ) में मैप करने के लिए ठीक हैं।


3
नल से क्यों बचें? वे बड़े पैमाने पर डेटाबेस में उपयोग किए जाते हैं।
रफी खाचदौरीयन

5
@RaffiKhatchadourian हाँ, डेटाबेस में नल का उपयोग किया जाता है, लेकिन समान रूप से समस्याग्रस्त हैं। इसे और इसे देखें और सभी उत्तरों और टिप्पणियों को पढ़ें । बूलियन अभिव्यक्तियों पर SQL नल के प्रभाव पर भी विचार करें: en.wikipedia.org/wiki/… ... यह क्वेरी त्रुटियों का समृद्ध स्रोत है।
स्टुअर्ट मार्क्स

1
@RaffiKhatchadourian क्योंकि nullबेकार है, इसीलिए। एसीसी। एक सर्वेक्षण में मैंने देखा (यह नहीं मिल सकता है), NPE जावा में नंबर 1 अपवाद है। एसक्यूएल एक उच्च स्तरीय प्रोग्रामिंग भाषा नहीं है, निश्चित रूप से कार्यात्मक नहीं है, जो अशक्त है, इसलिए यह परवाह नहीं करता है।
अभिजीत सरकार

91

हालांकि उत्तर 100% सही हैं, nullसूची के मामले को संभालने के लिए एक छोटा सुझाव वैकल्पिक के साथ ही :

 List<String> listOfStuffFiltered = Optional.ofNullable(listOfStuff)
                .orElseGet(Collections::emptyList)
                .stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

भाग Optional.ofNullable(listOfStuff).orElseGet(Collections::emptyList)आपको listOfStuffअशक्त होने पर अच्छी तरह से मामले को संभालने की अनुमति देगा और NullPointeException के साथ विफल होने के बजाय एक रिक्त सूची लौटाएगा।


2
मुझे यह पसंद है, अशक्त रूप से जाँच करने से बचता है।
क्रिस

1
यह सबसे अच्छा लगता है .. अच्छा और ठीक वही,
जिसकी

यह स्पष्ट रूप से अशक्त के लिए जाँच कर रहा है, केवल एक अलग तरीके से। यदि यह शून्य होने की अनुमति है, तो यह एक वैकल्पिक होना चाहिए, यह विचार है, सही है? वैकल्पिक के साथ सभी शून्य मानों को प्रतिबंधित करें। इसके अलावा, एक खाली सूची के बजाय अशक्त होने के लिए बुरा व्यवहार है, इसलिए यह दो कोड बदबू दिखाता है यदि मैं इसे देखता हूं: कोई वैकल्पिक उपयोग नहीं किया जा रहा है, और कोई भी खाली स्ट्रीम वापस नहीं किया जा रहा है। और बाद के 20 वर्षों के लिए उपलब्ध है, इसलिए यह परिपक्व है ...
कोस गडेला

क्या होगा अगर मैं खाली सूची के बजाय एक अशक्त वापसी करना चाहता हूं?
अश्विन RK

@AshburnRK यह एक बुरा अभ्यास है। आपको एक खाली सूची वापस करनी चाहिए।
जॉनी

69

स्टुअर्ट का जवाब एक महान व्याख्या प्रदान करता है, लेकिन मैं एक और उदाहरण प्रदान करना चाहता हूं।

मैं इस मामले में भाग गया जब एक reduceनल युक्त मान पर प्रदर्शन करने का प्रयास किया गया था (वास्तव में यह था LongStream.average(), जो कि एक प्रकार की कमी है)। चूंकि औसत () रिटर्न OptionalDouble, मैंने माना कि स्ट्रीम में नल हो सकते हैं, लेकिन इसके बजाय NullPointerException को फेंक दिया गया था। यह स्टुअर्ट के अशक्त शून्य के स्पष्टीकरण के कारण है ।

इसलिए, जैसा कि ओपी सुझाव देता है, मैंने एक फिल्टर जोड़ा जैसे:

list.stream()
    .filter(o -> o != null)
    .reduce(..);

या जैसा कि नीचे बताया गया है, जावा एपीआई द्वारा दिए गए विधेय का उपयोग करें:

list.stream()
    .filter(Objects::nonNull)
    .reduce(..);

मेलिंग सूची चर्चा से स्टुअर्ट जुड़े: ब्रायन गोएट्ज़ स्ट्रीम्स में नल पर


19

यदि आप केवल एक स्ट्रीम से शून्य मान फ़िल्टर करना चाहते हैं, तो आप बस java.util.Objects.nonNull (ऑब्जेक्ट) के लिए एक विधि संदर्भ का उपयोग कर सकते हैं । इसके प्रलेखन से:

इस विधि का प्रयोग एक विधेय के रूप में किया जाता है ,filter(Objects::nonNull)

उदाहरण के लिए:

List<String> list = Arrays.asList( null, "Foo", null, "Bar", null, null);

list.stream()
    .filter( Objects::nonNull )  // <-- Filter out null values
    .forEach( System.out::println );

यह प्रिंट करेगा:

Foo
Bar

7

एक उदाहरण कैसे अशक्त से बचने के लिए जैसे groupingBy से पहले फ़िल्टर का उपयोग करें

समूहीकरण से पहले अशक्त उदाहरणों को फ़िल्टर करें।

यहाँ एक उदाहरण है

MyObjectlist.stream()
            .filter(p -> p.getSomeInstance() != null)
            .collect(Collectors.groupingBy(MyObject::getSomeInstance));
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.