java - वैकल्पिक 8 पर जाव 8 ढूंढें पहले बनाम मानचित्र




nullpointerexception java-8 (3)

इस कोड को देखते हुए:

class Foo {
  Integer attr;
  public Integer getAttr() {return attr;}
}

List<Foo> list = new ArrayList<>();
list.add(new Foo());

list.stream().map(Foo::getAttr).findAny().orElse(null);  //A
list.stream().findAny().map(Foo::getAttr).orElse(null);  //B

लाइन ए फेंकता है

java.lang.NullPointerException: शून्य

जबकि लाइन बी रिटर्न नल

इस व्यवहार का कारण क्या है? दोनों findAny() और map() वापसी Optional<T>


सबसे पहले, आपके दो कोड स्निपेट map अलग-अलग कार्य हैं:

//            v--- stream intermediate operation
list.stream().map(Foo::getAttr).findAny().orElse(null);  //A
//                      v---- a Optional utility method 
list.stream().findAny().map(Foo::getAttr).orElse(null);  //B

और NullPointerException धारा # खोज में होता हैकभी ऑपरेशन, क्योंकि यह एक null मान स्वीकार नहीं कर सकता है। इसके कारण वैकल्पिकऑप्शन के बजाय वैकल्पिक । का उपयोग करता है। और स्ट्रीम के # दस्तावेज के दस्तावेज़ीकरण पहले ही दावा कर रहे हैं:

फेंकता है :

NullPointerException - अगर चयनित तत्व शून्य है

इसलिए यदि आप चाहते हैं कि आपका A कोड स्निपेट ठीक काम करता है, तो आपको स्ट्रीम # ढूंढने के लिए कॉल करने से पहले सभी null मानों को फ़िल्टर करना होगा, उदाहरण के लिए:

//when no elements in stream, `findAny` will be return a empty by Optional.empty()
//                                                       v   
list.stream().map(Foo::getAttr).filter(Objects::nonNull).findAny().orElse(null);//A

list.stream().map(Foo::getAttr).findAny().orElse(null);

धाराओं के लिए जावा डॉक स्ट्रीम का कहना है कि "इस स्ट्रीम के तत्वों को दिए गए फ़ंक्शन को लागू करने के परिणामों से मिलकर एक धारा देता है", और findAny () "एनलपॉन्टर अपॉसिशन वापस कर सकता है - यदि चुना गया तत्व शून्य है"। आपके क्लास फू में, पूर्णांक (नहीं int) डिफ़ॉल्ट रूप से शून्य पर सेट है क्योंकि घोषित किया जाता है लेकिन आरम्भ नहीं किया गया है प्रिमिटिज देखें जावा में डिफ़ॉल्ट मान और ऑब्जेक्ट इनिशियलाइज़ेशन

प्रारंभिक के लिए अलग है: ए) कक्षा सदस्यों (ऑब्जेक्ट्स और प्राइमिटिव) बी) लोकल वैरिएबल


वैसे यह स्पष्ट रूप से आदेश के कारण है जिसमें आप इन कार्यों को करते हैं और क्योंकि यह भी स्पष्ट रूप से कहता है: throws NullPointerException if the element selected is null

जब आप map(Foo::getAttr) को प्रभावी ढंग से मैप कर रहे हैं, तो आपकी स्ट्रीम में अब एक null ; इस प्रकार एक अपवाद के साथ कोई भी टूट जाता है (क्योंकि खोज findAny भी उस अशक्त पर लागू होता है)

दूसरा ऑपरेशन पहले Foo ऑब्जेक्ट को ढूंढता है, फिर इसे Foo::getAttr लिए मैप करता है (इसलिये इसे Optional.empty() लिए मानचित्रण किया जाता है), इस प्रकार या orElse को फोन किया जाता है।

इसके अलावा, यह अधिक मायने रखता है (मेरे लिए कम से कम):

 list.stream()
     .findAny()
     .flatMap(f -> Optional.ofNullable(f.getAttr()))
     .orElse(null);

flatMap Optional<Integer> (विशेषताओं) के लिए मैप करेगा, अगर यह empty है, तो orElse परिणाम प्राप्त करें।







optional