Optional.ifPresent () का उचित उपयोग


94

मैं जावा 8 में एपीआई की ifPresent()विधि को समझने की कोशिश कर रहा हूं Optional

मेरे पास सरल तर्क हैं:

Optional<User> user=...
user.ifPresent(doSomethingWithUser(user.get()));

लेकिन यह एक संकलन त्रुटि का परिणाम है:

ifPresent(java.util.functionError:(186, 74) java: 'void' type not allowed here)

बेशक मैं ऐसा कुछ कर सकता हूं:

if(user.isPresent())
{
  doSomethingWithUser(user.get());
}

लेकिन यह बिल्कुल एक बरबाद nullचेक की तरह है ।

यदि मैं इस में कोड बदलता हूं:

 user.ifPresent(new Consumer<User>() {
            @Override public void accept(User user) {
                doSomethingWithUser(user.get());
            }
        });

कोड डर्टियर हो रहा है, जो मुझे पुराने nullचेक पर वापस जाने के बारे में सोचता है ।

कोई विचार?

जवाबों:


154

Optional<User>.ifPresent()एक Consumer<? super User>तर्क के रूप में लेता है । आप इसे एक अभिव्यक्ति दे रहे हैं जिसका प्रकार शून्य है। इतना संकलन नहीं है।

एक उपभोक्ता को लंबोदर अभिव्यक्ति के रूप में लागू करने का इरादा है:

Optional<User> user = ...
user.ifPresent(theUser -> doSomethingWithUser(theUser));

या यहां तक ​​कि सरल, एक विधि संदर्भ का उपयोग कर:

Optional<User> user = ...
user.ifPresent(this::doSomethingWithUser);

यह मूल रूप से एक ही बात है

Optional<User> user = ...
user.ifPresent(new Consumer<User>() {
    @Override
    public void accept(User theUser) {
        doSomethingWithUser(theUser);
    }
});

विचार यह है कि doSomethingWithUser()विधि कॉल केवल तभी निष्पादित होगी जब उपयोगकर्ता मौजूद होगा। आपका कोड सीधे मेथड कॉल को निष्पादित करता है, और इसके शून्य परिणाम को पास करने की कोशिश करता है ifPresent()


2
उस कोड को क्लट किया जा रहा है .. एक अशक्त चेक बहुत अधिक क्लीनर होगा। ? आपको नहीं लगता कि विशेष रूप से कि doSomethingWithUser एक स्थिर विधि नहीं है
Rayman

4
कौन सा कोड? आपको जो उपयोग करना चाहिए वह दूसरा है, जो इंस्टेंस (यानी गैर-स्थिर) विधि doSomethingWithUser () कहता है। मैं नहीं देखता कि यह कैसे बरबाद है। अंतिम कोड आपको लैंबडा के पूर्व-लैम्ब्डा दुनिया के बराबर समझाने के लिए है। इसका उपयोग न करें।
जेबी निज़ैट

2
हां, लेकिन आप अनाम कक्षाओं के लिए उपयोग किए जा सकते हैं और इस प्रकार समझ सकते हैं कि लैम्ब्डा एक अनाम वर्ग के समकक्ष देखकर क्या करता है। यही तो बात है।
जेबी निज़ैट

1
आपको संशोधित करने के लिए कुछ भी नहीं है। इसे वैसे ही छोड़ दें, और दूसरे उदाहरण का उपयोग करें:user.ifPresent(this::doSomethingWithUser);
जेबी निज़ेट

10
@rayman यदि आपके पास एक फ़ंक्शन है जो Optional<User>वहां लौटता है, तो इसे अक्सर स्थानीय चर में संग्रहीत करने की आवश्यकता नहीं होती है। बस विधि फोन कॉल:funcThatMightReturnUser().ifPresent(this::doSomethingWithUser);
स्टुअर्ट मार्क्स

19

@ JBNizet के उत्तर के अलावा, मेरा सामान्य उपयोग मामला ifPresentसंयोजन .isPresent()और करने के लिए है .get():

पुराना तरीका:

Optional opt = getIntOptional();
if(opt.isPresent()) {
    Integer value = opt.get();
    // do something with value
}

नया रास्ता:

Optional opt = getIntOptional();
opt.ifPresent(value -> {
    // do something with value
})

यह, मेरे लिए, अधिक सहज है।


7

फ्लैटपाइप का इस्तेमाल करें। यदि कोई मान मौजूद है, तो flatMap एक अनुक्रमिक स्ट्रीम देता है जिसमें केवल उस मान होता है, अन्यथा एक खाली स्ट्रीम देता है। इसलिए उपयोग करने की कोई आवश्यकता नहीं है ifPresent()। उदाहरण:

list.stream().map(data -> data.getSomeValue).map(this::getOptinalValue).flatMap(Optional::stream).collect(Collectors.toList());

3
वैकल्पिक :: स्ट्रीम को java9 की आवश्यकता है
avmohan

7

जब आप इसे सरल बना सकते हैं तो जटिल कोड क्यों लिखें?

वास्तव में, यदि आप Optionalकक्षा का उपयोग करने जा रहे हैं , तो सबसे सरल कोड वह है जो आपने पहले ही लिखा है ...

if (user.isPresent())
{
    doSomethingWithUser(user.get());
}

इस कोड के होने के फायदे हैं

  1. पठनीय
  2. डीबग करना आसान (ब्रेकपॉइंट)
  3. मुश्किल नहीं

सिर्फ इसलिए कि Oracle ने Optionalजावा 8 में क्लास को जोड़ा है, इसका मतलब यह नहीं है कि इस क्लास को हर हाल में इस्तेमाल किया जाना चाहिए।


1
IfPresent का उपयोग करने का मुख्य लाभ यह है कि यह आपको कभी भी कॉल करने की आवश्यकता को हटा देता है () मैन्युअल रूप से। कॉलिंग मिल () मैन्युअल रूप से त्रुटि प्रवण है, क्योंकि पहले चेक करना भूल जाना आसान है, लेकिन पहले तो यह भूलना असंभव है कि यदि आप उपयोग करते हैं तो आप भूल सकते हैं यदि आप का उपयोग करते हैं
dustinroepsch

1
ठीक है और हर बार जब आप 'यूजर' ऑब्जेक्ट का उपयोग करेंगे, तो आपको .ifPresent () को कॉल करना चाहिए। कोड जल्दी से अपठनीय हो जाएगा क्योंकि आप बहुत अधिक समय .ifPresent () पढ़ेंगे!
विद्वान

2
अपने प्रोफ़ाइल पृष्ठ ( VB.Net , Netbeans , SqlServer , PostGresql , MySql , और Linq) पर गलत वर्तनी को ठीक करने के लिए , आप मेरी सेवा का उपयोग कर सकते हैं । इसके अलावा एक शब्दसूची भी है
पीटर मॉर्टेंसन

7

आप इस तरह विधि संदर्भ का उपयोग कर सकते हैं:

user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser);

विधि को एक paremeter के रूप में वस्तु ifPresent()मिलती है Consumerऔर ( JavaDoc से ): "यदि कोई मान मौजूद है, तो मूल्य के साथ निर्दिष्ट ग्राहक को आमंत्रित करें।" मान यह आपका परिवर्तनशील है user

या यदि इस विधि doSomethingWithUserमें है Userवर्ग और यह नहीं है static, तो आप इस तरह विधि संदर्भ का उपयोग कर सकते हैं:

user.ifPresent(this::doSomethingWithUser);

1
लेकिन doSomethingWithUser एक स्थिर विधि नहीं है और न ही यह क्लास है।
रेमन

@rayman Ok, अगर स्थिर नहीं है तो आप ऐसा कर सकते हैं:user.ifPresent(new ClassNameWhereMethodIs()::doSomethingWithUser);
Aleksandr Podkutin

7
@AleksandrPodkutin आपको केवल एक विधि को चलाने के लिए कक्षा का एक नया उदाहरण नहीं बनाना चाहिए, ओपी से ऐसा लगता है कि विधि उसी कक्षा में है जैसा कि इसे कहा जा रहा है, इस प्रकार उसका उपयोग करना चाहिएuser.ifPresent(this::doSomethingWithUser);
Marv

@Marv मैं किसी भी प्रतिज्ञान प्रपत्र ओपी को नहीं देखता कि यह उसी कक्षा में है। लेकिन अगर आपके पास ऐसी भावनाएं हैं, तो मैं सहमत हूं कि उसे उपयोग करना होगा user.ifPresent(this::doSomethingWithUser);। मैं इसे अपने जवाब में जोड़ दूंगा।
१५:०२ पर अलेक्सांद्र पोडकुटिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.