लैम्ब्डा के उपयोग से तुलना नहीं की जाती है


111

मेरे पास कुछ उपयोगकर्ता वस्तुओं के साथ एक सूची है और मैं सूची को क्रमबद्ध करने की कोशिश कर रहा हूं, लेकिन केवल विधि संदर्भ का उपयोग करके काम करता है, लंबर अभिव्यक्ति के साथ संकलक एक त्रुटि देता है:

List<User> userList = Arrays.asList(u1, u2, u3);
userList.sort(Comparator.comparing(u -> u.getName())); // works
userList.sort(Comparator.comparing(User::getName).reversed()); // works
userList.sort(Comparator.comparing(u -> u.getName()).reversed()); // Compiler error

त्रुटि:

com\java8\collectionapi\CollectionTest.java:35: error: cannot find symbol
            userList.sort(Comparator.comparing(u -> u.getName()).reversed());
                                                     ^
symbol:   method getName()
location: variable u of type Object
1 error

जवाबों:


145

यह कंपाइलर के टाइप अवर तंत्र में एक कमजोरी है। uलैम्ब्डा के प्रकार का अनुमान लगाने के लिए, लैम्ब्डा के लिए लक्ष्य प्रकार को स्थापित करने की आवश्यकता है। यह निम्नानुसार पूरा किया जाता है। userList.sort()प्रकार के तर्क की अपेक्षा कर रहा है Comparator<User>। पहली पंक्ति में, Comparator.comparing()लौटने की जरूरत है Comparator<User>। यह है कि संकेत मिलता है Comparator.comparing()एक की जरूरत है Functionकि एक लेता Userतर्क। इस प्रकार पहली पंक्ति में लैम्ब्डा में, uप्रकार Userऔर सब कुछ काम करना चाहिए ।

दूसरी और तीसरी पंक्ति में, कॉल करने की उपस्थिति से लक्ष्य टाइपिंग बाधित होती है reversed()। मुझे पूरा यकीन नहीं है कि क्यों; रिसीवर और रिटर्न प्रकार दोनों reversed()हैं Comparator<T>इसलिए ऐसा लगता है कि लक्ष्य प्रकार को वापस रिसीवर को प्रचारित किया जाना चाहिए, लेकिन यह नहीं है। (जैसा मैंने कहा, यह एक कमजोरी है।)

दूसरी पंक्ति में, विधि संदर्भ अतिरिक्त प्रकार की जानकारी प्रदान करता है जो इस अंतर को भरता है। यह जानकारी, तीसरी पंक्ति में अनुपस्थित रहती है तो संकलक infers uहोने के लिए Object(अंतिम उपाय के अनुमान फ़ॉलबैक) है, जो विफल रहता है।

जाहिर है अगर आप एक विधि संदर्भ का उपयोग कर सकते हैं, तो वह करें और यह काम करेगा। कभी-कभी आप एक विधि संदर्भ का उपयोग नहीं कर सकते हैं, उदाहरण के लिए, यदि आप एक अतिरिक्त पैरामीटर पास करना चाहते हैं, तो आपको एक लैम्ब्डा अभिव्यक्ति का उपयोग करना होगा। उस स्थिति में आप लैम्बडा में एक स्पष्ट पैरामीटर प्रकार प्रदान करेंगे:

userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());

यह संभव है कि कंपाइलर को भविष्य के रिलीज में इस मामले को कवर करने के लिए बढ़ाया जाए।


28
लैम्ब्डा को स्पष्ट रूप से टाइप किया गया है (मापदंडों के लिए कोई प्रकट प्रकार नहीं) और स्पष्ट रूप से टाइप किया गया है ; विधि संदर्भों को सटीक (कोई अधिभार नहीं) और अक्षम में विभाजित किया गया है । जब किसी रिसीवर पोजीशन में जेनेरिक मेथड कॉल में लैम्बडा आर्ग्युमेंट्स होते हैं, और टाइप के पैरामीटर अन्य तर्कों से पूरी तरह से अनुमान नहीं लगाया जा सकता है, तो आपको या तो एक स्पष्ट लैम्ब्डा, एक सटीक मेथड रेफरी, टारगेट टाइप कास्ट, या स्पष्ट टाइप के लिए उपलब्ध कराने की जरूरत है। आगे बढ़ने के लिए आवश्यक अतिरिक्त प्रकार की जानकारी प्रदान करने के लिए सामान्य विधि कॉल।
ब्रायन गोएट्ज

1
@StuartMarks, आप "पूरी तरह से आश्वस्त नहीं हैं" क्यों कंपाइलर इस तरह से काम कर रहा है। लेकिन भाषा विनिर्देश क्या कहता है? क्या भाषा विनिर्देश के अनुसार, सामान्य प्रकार निर्धारित करने के लिए पर्याप्त जानकारी होनी चाहिए? यदि हां, तो यह एक कंपाइलर बग है और इसे दर्ज किया जाना चाहिए और उसके अनुसार निपटा जाना चाहिए। अन्यथा यह एक ऐसा क्षेत्र है जिसमें जावा भाषा को सुधारना चाहिए। यह किसका है?
गैरेट विल्सन

8
मुझे लगता है कि हम ब्रायन की टिप्पणियों को निश्चित मान सकते हैं, क्योंकि उन्होंने प्रश्न में विनिर्देश लिखा है :-)
मिनिमम

1
अफसोस की बात यह है कि यह उलट काम नहीं कर रहा है, जबकि यह उलटा काम नहीं कर रहा है।
क्रिस 311

90

आप इस सीमा के आस-दो तर्क का उपयोग करके काम कर सकते हैं Comparator.comparingके साथ Comparator.reverseOrder()दूसरा तर्क के रूप में:

users.sort(comparing(User::getName, reverseOrder()));

4
अच्छा लगा। मुझे स्पष्ट रूप से टाइप किए गए लंबोदा का उपयोग करने से बेहतर यह पसंद है। या, बेहतर अभी तक users.sort(reverseOrder(comparing(User::getName)));,।
रोल

10
ध्यान दें कि reverseOrder(Comparator<T>)ऊपर दी गई विधि अंदर है java.util.Collections, अंदर नहीं Comparator
रोलीव करें
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.