मैं अपने दूसरे उत्तर के लिए उपयोगकर्ता srborlongan द्वारा प्रस्तावित संपादन के आधार पर यह दूसरा उत्तर जोड़ रहा हूं । मुझे लगता है कि प्रस्तावित तकनीक दिलचस्प थी, लेकिन यह वास्तव में मेरे जवाब को संपादित करने के रूप में उपयुक्त नहीं था। अन्य सहमत हुए और प्रस्तावित संपादन को वोट दिया गया। (मैं मतदाताओं में से एक नहीं था।) तकनीक में योग्यता है, हालांकि। यह सबसे अच्छा होता अगर srborlongan ने अपना उत्तर स्वयं पोस्ट किया होता। यह अभी तक नहीं हुआ है, और मैं नहीं चाहता था कि स्टैकऑवरफ्लो के मिस्ट्स में तकनीक खो जाए, इतिहास को संपादित करें, इसलिए मैंने इसे एक अलग उत्तर के रूप में खुद को बनाने का फैसला किया।
मूल रूप से तकनीक Optionalएक चतुर तरीके से कुछ तरीकों का उपयोग करने से बचने के लिए एक टर्नरी ऑपरेटर ( ? :) या यदि या किसी अन्य कथन का उपयोग करने के लिए है ।
मेरा इनलाइन उदाहरण इस तरह से फिर से लिखा जाएगा:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
.findFirst();
एक सहायक विधि का उपयोग करने वाला मेरा उदाहरण इस तरह से फिर से लिखा जाएगा:
/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon
* whether a value is present.
*/
static <T> Stream<T> streamopt(Optional<T> opt) {
return opt.map(Stream::of)
.orElseGet(Stream::empty);
}
Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();
टीका
आइए सीधे मूल बनाम संशोधित संस्करणों की तुलना करें:
// original
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
// modified
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
मूल सीधा है अगर काम करने वाला दृष्टिकोण: हमें एक Optional<Other>; यदि इसका कोई मान है, तो हम उस मान से युक्त स्ट्रीम लौटाते हैं, और यदि इसका कोई मूल्य नहीं है, तो हम एक खाली स्ट्रीम लौटाते हैं। बहुत सरल और समझाने में आसान।
संशोधन चतुर है और इसका लाभ यह है कि यह सशर्त से बचा जाता है। (मुझे पता है कि कुछ लोग टर्नरी ऑपरेटर को नापसंद करते हैं। यदि इसका दुरुपयोग किया जाता है तो यह वास्तव में कोड को समझना मुश्किल बना सकता है।) हालांकि, कभी-कभी चीजें बहुत चालाक हो सकती हैं। संशोधित कोड भी एक के साथ शुरू होता है Optional<Other>। फिर यह कॉल Optional.mapकरता है जिसे निम्नानुसार परिभाषित किया गया है:
यदि कोई मान मौजूद है, तो उसे प्रदान की गई मैपिंग फ़ंक्शन लागू करें, और यदि परिणाम गैर-शून्य है, तो परिणाम का वर्णन करते हुए एक वैकल्पिक लौटाएं। अन्यथा एक खाली वैकल्पिक लौटें।
map(Stream::of)कॉल एक रिटर्न Optional<Stream<Other>>। यदि कोई मूल्य इनपुट वैकल्पिक में मौजूद था, तो लौटे वैकल्पिक में एक स्ट्रीम होता है जिसमें एकल अन्य परिणाम होता है। लेकिन यदि मान मौजूद नहीं था, तो परिणाम एक खाली वैकल्पिक है।
इसके बाद, कॉल orElseGet(Stream::empty)प्रकार का मान लौटाता है Stream<Other>। यदि इसका इनपुट मान मौजूद है, तो उसे वह मान मिलता है, जो एकल-तत्व है Stream<Other>। अन्यथा (यदि इनपुट मान अनुपस्थित है) तो यह खाली हो जाता है Stream<Other>। तो परिणाम सही है, मूल सशर्त कोड के समान है।
मेरे जवाब पर चर्चा कर रहे टिप्पणियों में, अस्वीकार किए गए संपादन के संबंध में, मैंने इस तकनीक को "अधिक संक्षिप्त लेकिन साथ ही अधिक अस्पष्ट" बताया था। मैं इसी से खड़ा हूं। मुझे यह पता लगाने में थोड़ा समय लगा कि यह क्या कर रहा था, और मुझे यह बताने में भी थोड़ा समय लगा कि यह क्या कर रहा है। कुंजी सूक्ष्मता से परिवर्तन Optional<Other>है Optional<Stream<Other>>। एक बार जब आप इसे दबा लेते हैं तो यह समझ में आता है, लेकिन यह मेरे लिए स्पष्ट नहीं था।
मैं स्वीकार करता हूँ, हालांकि, यह है कि शुरू में अस्पष्ट हैं चीजें समय के साथ मुहावरेदार हो सकती हैं। यह हो सकता है कि यह तकनीक व्यवहार में सबसे अच्छा तरीका है, कम से कम जब तक Optional.streamजोड़ा नहीं जाता है (यदि यह कभी भी हो)।
अद्यतन: Optional.stream JDK 9 में जोड़ा गया है।
.flatMap(Optional::toStream)आपके संस्करण के साथ आप वास्तव में देखते हैं कि क्या चल रहा है।