इन दोनों विधियों में क्या अंतर है: Optional.flatMap()
औरOptional.map()
?
एक उदाहरण की सराहना की जाएगी।
Stream#flatMap
और Optional#flatMap
।
इन दोनों विधियों में क्या अंतर है: Optional.flatMap()
औरOptional.map()
?
एक उदाहरण की सराहना की जाएगी।
Stream#flatMap
और Optional#flatMap
।
जवाबों:
map
यदि फ़ंक्शन आपकी ज़रूरत की वस्तु लौटाता है या flatMap
यदि फ़ंक्शन रिटर्न करता है तो उपयोग करें Optional
। उदाहरण के लिए:
public static void main(String[] args) {
Optional<String> s = Optional.of("input");
System.out.println(s.map(Test::getOutput));
System.out.println(s.flatMap(Test::getOutputOpt));
}
static String getOutput(String input) {
return input == null ? null : "output for " + input;
}
static Optional<String> getOutputOpt(String input) {
return input == null ? Optional.empty() : Optional.of("output for " + input);
}
दोनों प्रिंट स्टेटमेंट एक ही बात को प्रिंट करते हैं।
[flat]Map
कभी ए के साथ मैपिंग फ़ंक्शन को कहेंगे input == null
? मेरी समझ यह है कि Optional
यदि यह अनुपस्थित है तो शॉर्टकट्स - [JavaDoc] ( docs.oracle.com/javase/8/docs/api/java/util/… ) इसे बैक अप लगता है - " यदि कोई मान मौजूद है, तो लागू करें .." । "
Optional.of(null)
एक है Exception
। Optional.ofNullable(null) == Optional.empty()
।
वे दोनों वैकल्पिक के प्रकार से कुछ के लिए एक फ़ंक्शन लेते हैं।
map()
वैकल्पिक रूप से आपके पास " जैसा है " फ़ंक्शन लागू होता है:
if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));
यदि आपका फ़ंक्शन किसी फ़ंक्शन से है तो क्या होता है T -> Optional<U>
?
आपका रिजल्ट अब एOptional<Optional<U>>
!
इस flatMap()
बारे में यही है: यदि आपका फ़ंक्शन पहले से ही रिटर्न करता है Optional
, flatMap()
तो थोड़ा अधिक होशियार है और यह डबल रैप नहीं करता है, लौट रहा है Optional<U>
।
यह दो कार्यात्मक मुहावरों की संरचना है: map
और flatten
।
नोट: - नीचे नक्शा और फ्लैटमैप फ़ंक्शन का चित्रण है, अन्यथा वैकल्पिक रूप से केवल रिटर्न प्रकार के रूप में उपयोग करने के लिए डिज़ाइन किया गया है।
जैसा कि आप पहले से ही जानते होंगे कि ऑप्शनल एक तरह का कंटेनर होता है जिसमें एक भी ऑब्जेक्ट नहीं हो सकता है या नहीं, इसलिए इसका उपयोग आप कहीं भी कर सकते हैं जहाँ आप एक शून्य मान की आशा करते हैं (यदि आप वैकल्पिक रूप से ठीक से उपयोग करते हैं तो आप कभी भी एनपीई नहीं देख सकते हैं)। उदाहरण के लिए यदि आपके पास एक ऐसी विधि है जो किसी व्यक्ति वस्तु की अपेक्षा करती है जो अशक्त हो सकती है, तो आप विधि को कुछ इस तरह लिखना चाहते हैं:
void doSome(Optional<Person> person){
/*and here you want to retrieve some property phone out of person
you may write something like this:
*/
Optional<String> phone = person.map((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
class Person{
private String phone;
//setter, getters
}
यहां आपने एक स्ट्रिंग प्रकार लौटाया है जो स्वचालित रूप से एक वैकल्पिक प्रकार में लिपटा है।
अगर व्यक्ति वर्ग ऐसा दिखता है, तो फोन भी वैकल्पिक है
class Person{
private Optional<String> phone;
//setter,getter
}
इस मामले में मानचित्र फ़ंक्शन को लागू करने से लौटे मूल्य को वैकल्पिक में लपेटा जाएगा और कुछ इस तरह से मिलेगा:
Optional<Optional<String>>
//And you may want Optional<String> instead, here comes flatMap
void doSome(Optional<Person> person){
Optional<String> phone = person.flatMap((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
पुनश्च; जब तक आप NullPointerException के बिना नहीं रह सकते, तब तक इसे वैकल्पिक () के साथ चेक किए बिना वैकल्पिक तरीके से कॉल करें।
Person
दुरुपयोग कर रही है Optional
। यह Optional
इस तरह से सदस्यों पर उपयोग करने के लिए एपीआई के इरादे के खिलाफ है - देखें mail.openjdk.java.net/pipermail/jdk8-dev/2013-Seture/…
दो कार्यों के स्रोत कोड पर एक नज़र डालने में मुझे क्या मदद मिली।
मानचित्र - एक वैकल्पिक में परिणाम को लपेटता है।
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value)); //<--- wraps in an optional
}
}
flatMap - 'कच्ची' वस्तु लौटाता है
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value)); //<--- returns 'raw' object
}
}
flatMap
"कच्ची 'वस्तु" रिटर्न "से आपका क्या तात्पर्य है ? flatMap
मैप की गई वस्तु को "लिपटे" में भी लौटाता है Optional
। अंतर यह है कि के मामले में flatMap
, मैपर फ़ंक्शन मैप की गई वस्तु को लपेटता है Optional
जबकि map
स्वयं ऑब्जेक्ट को लपेटता है Optional
।
Optional.map()
:प्रत्येक तत्व को लेता है और यदि मान मौजूद है, तो यह फ़ंक्शन को दिया जाता है:
Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);
अब जोड़े में तीन में से एक मान है: true
या false
एक वैकल्पिक में लिपटे , यदि optionalValue
मौजूद था, या एक खाली वैकल्पिक अन्यथा।
यदि आपको उस परिणाम को संसाधित करने की आवश्यकता नहीं है जिसे आप बस उपयोग कर सकते हैं ifPresent()
, तो इसका रिटर्न मान नहीं है:
optionalValue.ifPresent(results::add);
Optional.flatMap()
:धाराओं के समान विधि के समान काम करता है। धाराओं की धारा को समतल करता है। इस अंतर के साथ कि यदि मूल्य प्रस्तुत किया जाता है तो इसे फ़ंक्शन पर लागू किया जाता है। अन्यथा, एक खाली वैकल्पिक वापस आ गया है।
आप वैकल्पिक मूल्य फ़ंक्शन कॉल करने के लिए इसका उपयोग कर सकते हैं।
मान लीजिए कि हमारे पास तरीके हैं:
public static Optional<Double> inverse(Double x) {
return x == 0 ? Optional.empty() : Optional.of(1 / x);
}
public static Optional<Double> squareRoot(Double x) {
return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
}
तब आप व्युत्क्रम के वर्गमूल की गणना कर सकते हैं, जैसे:
Optional<Double> result = inverse(-4.0).flatMap(MyMath::squareRoot);
या, यदि आप पसंद करते हैं:
Optional<Double> result = Optional.of(-4.0).flatMap(MyMath::inverse).flatMap(MyMath::squareRoot);
यदि या तो inverse()
या squareRoot()
रिटर्न Optional.empty()
, परिणाम खाली है।
Optional<Double>
में रिटर्न टाइप के रूप में टाइप होता है।
ठीक है। आप केवल जब तुम नेस्टेड Optionals सामना कर रहे हैं उपयोग 'flatMap' की जरूरत है । यहाँ उदाहरण है।
public class Person {
private Optional<Car> optionalCar;
public Optional<Car> getOptionalCar() {
return optionalCar;
}
}
public class Car {
private Optional<Insurance> optionalInsurance;
public Optional<Insurance> getOptionalInsurance() {
return optionalInsurance;
}
}
public class Insurance {
private String name;
public String getName() {
return name;
}
}
public class Test {
// map cannot deal with nested Optionals
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.map(Car::getOptionalInsurance) // ① leads to a Optional<Optional<Insurance>
.map(Insurance::getName); // ②
}
}
स्ट्रीम की तरह, वैकल्पिक # मानचित्र एक वैकल्पिक द्वारा लिपटे मान को लौटाएगा। इसलिए हमें एक नेस्टेड ऑप्शनल मिलता है - Optional<Optional<Insurance>
। और we पर, हम इसे एक बीमा उदाहरण के रूप में मैप करना चाहते हैं, इसी तरह यह त्रासदी हुई है। रूट नेस्टेड ऑप्शनल है। यदि हम गोले की परवाह किए बिना मुख्य मूल्य प्राप्त कर सकते हैं, तो हम इसे पूरा कर लेंगे। यही फ्लैटप्लेट करता है।
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.flatMap(Car::getOptionalInsurance)
.map(Insurance::getName);
}
अंत में, मैंने आपको जावा 8 इन एक्शन के बारे में बताया, यदि आप Java8 को व्यवस्थित रूप से अध्ययन करना चाहते हैं।