Comparator.reversed () ল্যাম্বডা ব্যবহার করে সংকলন করে না


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()দরকার । সুতরাং প্রথম লাইনে ল্যাম্বডায় অবশ্যই টাইপ হওয়া উচিত এবং সমস্ত কিছুই কাজ করে।FunctionUseruUser

দ্বিতীয় এবং তৃতীয় লাইনে লক্ষ্য টাইপিং কলটির উপস্থিতি দ্বারা ব্যাহত হয় reversed()। আমি কেন পুরোপুরি নিশ্চিত নই; উভয় রিসিভার এবং রিটার্ন টাইপ reversed()হয় Comparator<T>, তাই এটি লক্ষ্য টাইপ ফিরে রিসিভার প্রচারিত হবে মত মনে হয়, কিন্তু এটা নয়। (যেমনটি আমি বলেছিলাম, এটি একটি দুর্বলতা))

দ্বিতীয় লাইনে, পদ্ধতি রেফারেন্সটি অতিরিক্ত ধরণের তথ্য সরবরাহ করে যা এই ফাঁকটি পূর্ণ করে। এই তথ্যটি তৃতীয় লাইন থেকে অনুপস্থিত, তাই সংকলকটি অন্তর্ভুক্ত uকরে Object(শেষ অবলম্বনের অনুমান ফালব্যাক), যা ব্যর্থ হয়।

অবশ্যই আপনি যদি কোনও পদ্ধতি রেফারেন্স ব্যবহার করতে পারেন তবে তা করুন এবং এটি কাজ করবে। কখনও কখনও আপনি কোনও পদ্ধতি রেফারেন্স ব্যবহার করতে পারবেন না, যেমন আপনি যদি অতিরিক্ত প্যারামিটারটি পাস করতে চান তবে আপনাকে ল্যাম্বডা এক্সপ্রেশন ব্যবহার করতে হবে। সেক্ষেত্রে আপনি ল্যাম্বডায় একটি স্পষ্ট প্যারামিটার প্রকার সরবরাহ করবেন:

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

ভবিষ্যতে প্রকাশে এই কেসটি কভার করতে সংকলকটির বর্ধিত করা সম্ভব হতে পারে।


28
ল্যাম্বডাস স্পষ্টভাবে টাইপযুক্ত (প্যারামিটারগুলির জন্য কোনও প্রকাশিত ধরণের নয়) এবং সুস্পষ্টভাবে টাইপ করা বিভক্ত ; পদ্ধতি রেফারেন্সগুলি নির্ভুল (কোনও ওভারলোড নেই) এবং নিখুঁতভাবে বিভক্ত । যখন কোনও জেনেরিক পদ্ধতিতে কল গ্রহণের স্থানে ল্যাম্বদা আর্গুমেন্ট থাকে এবং ধরণের পরামিতিগুলি অন্য যুক্তি থেকে পুরোপুরি অনুমান করা যায় না, আপনাকে স্পষ্টত ল্যাম্বডা, একটি সঠিক পদ্ধতি রেফ, একটি টার্গেট টাইপ কাস্ট, বা স্পষ্টত ধরণের সাক্ষী সরবরাহ করতে হবে জেনেরিক পদ্ধতি কলটি এগিয়ে যাওয়ার জন্য প্রয়োজনীয় অতিরিক্ত ধরণের তথ্য সরবরাহ করতে।
ব্রায়ান গয়েটজ

1
@ স্টার্টমার্কস, আপনি "কেন পুরোপুরি নিশ্চিত নন" সংকলকটি এরূপ আচরণ করছে। তবে ভাষার স্পেসিফিকেশন কী বলে? ভাষার স্পেসিফিকেশন অনুযায়ী জেনেরিক প্রকারগুলি নির্ধারণ করার জন্য পর্যাপ্ত তথ্য থাকতে হবে? যদি তা হয় তবে এটি একটি সংকলক বাগ এবং ফাইল করা উচিত এবং সেই অনুযায়ী কাজ করা উচিত। অন্যথায় এটি এমন একটি অঞ্চল যেখানে জাভা ভাষার উন্নতি করা উচিত। ইহা কোনটা?
গ্যারেট উইলসন

8
আমি মনে করি আমরা ব্রায়ানের মন্তব্যগুলিকে যথার্থ হিসাবে বিবেচনা করতে পারি, কারণ তিনি প্রশ্নে স্পেসিফিকেশন লিখেছিলেন :-)
মিনিমালিস

1
দুঃখের বিষয় এইগুলির কোনওটিই ব্যাখ্যা করে না যে এটি বিপরীতমুখী হয়ে কাজ করা অবস্থায় কেন বিপরীত কাজ করছে।
Chris311

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
ঘোরা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.