জাভা 8 স্ট্রিমের .মিন () এবং .ম্যাক্স (): কেন এটি সংকলন করে?


215

দ্রষ্টব্য: এই প্রশ্নটি একটি মৃত লিঙ্ক থেকে উদ্ভূত যা পূর্ববর্তী SO প্রশ্ন ছিল, তবে এখানে ...

এই কোডটি দেখুন ( দ্রষ্টব্য: আমি জানি যে এই কোডটি "কাজ করবে না" এবং এটি Integer::compareব্যবহার করা উচিত - আমি কেবল এটি লিঙ্কিত প্রশ্ন থেকে বের করেছি ):

final ArrayList <Integer> list 
    = IntStream.rangeClosed(1, 20).boxed().collect(Collectors.toList());

System.out.println(list.stream().max(Integer::max).get());
System.out.println(list.stream().min(Integer::min).get());

এর জাভাদোক অনুযায়ী .min()এবং .max()উভয়ের যুক্তি হওয়া উচিত a Comparator। তবুও এখানে পদ্ধতির উল্লেখগুলি Integerক্লাসের স্থির পদ্ধতির সাথে সম্পর্কিত ।

সুতরাং, কেন এই আদৌ সংকলন করে?


6
মনে রাখবেন এটি সঠিকভাবে কাজ করে না, এটি এর Integer::compareপরিবর্তে Integer::maxএবং ব্যবহার করা উচিত Integer::min
ক্রিস্টোফার হামারস্ট্রিম

@ ক্রিস্টোফারহ্যামারস্ট্রিম আমি জানি যে; আমি কীভাবে কোডটি বের করার আগে বলেছিলাম নোট করুন "আমি জানি, এটি অযৌক্তিক"
fge

3
আমি আপনাকে সংশোধন করার চেষ্টা করছিলাম না, আমি সাধারণভাবে লোকদের বলছি। আপনি এটিকে এমন শব্দ করেছেন যেন আপনি ভেবেছিলেন যে অংশটি অযৌক্তিক তা হ'ল পদ্ধতিগুলি পদ্ধতি Integerনয় Comparator
ক্রিস্টোফার হামারস্ট্রিম

উত্তর:


242

আমাকে এখানে কী ঘটছে তা ব্যাখ্যা করতে দাও, কারণ এটি সুস্পষ্ট নয়!

প্রথমে Stream.max()একটি উদাহরণ গ্রহণ করে Comparatorযাতে স্রোতের আইটেমগুলি একে অপরের তুলনায় তুলনামূলকভাবে সর্বনিম্ন বা সর্বাধিক সন্ধান করতে পারে, কিছু অনুকূল ক্রমে যাতে আপনাকে খুব বেশি চিন্তা করার দরকার নেই।

সুতরাং প্রশ্ন অবশ্যই, কেন Integer::maxগৃহীত হয়? সর্বোপরি এটি তুলনামূলক নয়!

উত্তরটি জাভা ৮.-তে নতুন ল্যাম্বদা কার্যকারিতাটি যেভাবে কাজ করে তা এই ধারণার উপর নির্ভর করে যা অনানুষ্ঠানিকভাবে "একক বিমূর্ত পদ্ধতি" ইন্টারফেস বা "এসএএম" ইন্টারফেস হিসাবে পরিচিত। ধারণাটি হ'ল একটি বিমূর্ত পদ্ধতি সহ যে কোনও ইন্টারফেস স্বয়ংক্রিয়ভাবে কোনও ল্যাম্বডা - বা পদ্ধতি রেফারেন্স দ্বারা প্রয়োগ করা যেতে পারে - যার পদ্ধতির স্বাক্ষর ইন্টারফেসের এক পদ্ধতির সাথে মিল রয়েছে। সুতরাং Comparatorইন্টারফেস পরীক্ষা করা (সহজ সংস্করণ):

public Comparator<T> {
    T compare(T o1, T o2);
}

যদি কোনও পদ্ধতি কোনও সন্ধান করে Comparator<Integer>, তবে এটি মূলত এই স্বাক্ষরটি সন্ধান করছে:

int xxx(Integer o1, Integer o2);

আমি "XXX" ব্যবহার কারণ পদ্ধতির নাম ম্যাচিং উদ্দেশ্যে ব্যবহার করা হয় না

অতএব, উভয়ই Integer.min(int a, int b)এবং Integer.max(int a, int b)পর্যাপ্ত যে অটোবক্সিং এটিকে Comparator<Integer>কোনও পদ্ধতি প্রসঙ্গে একটি হিসাবে উপস্থিত হতে দেয় ।


28
অথবা বিকল্পভাবে: list.stream().mapToInt(i -> i).max().get()
Assylias

13
@ এ্যাসেলিয়াস আপনি যদিও এর .getAsInt()পরিবর্তে ব্যবহার করতে চান get(), যেমন আপনি একটি ব্যবহার করছেন OptionalInt
স্কিভি

... যখন আমরা যা চেষ্টা করছি তা হ'ল কোনও max()ফাংশনে একটি কাস্টম তুলনা সরবরাহ করা !
মনু 343726

এটি লক্ষণীয় যে এই "এসএএম ইন্টারফেস "টিকে আসলে" ফাংশনাল ইন্টারফেস "বলা হয় এবং Comparatorডকুমেন্টেশনের দিকে তাকানো আমরা দেখতে পাই যে এটি টীকাটি দিয়ে সজ্জিত @FunctionalInterface। এই সাজসজ্জাটি এমন যাদু যা মঞ্জুরি দেয় Integer::maxএবং এ Integer::minতে রূপান্তরিত করে Comparator
ক্রিস কেরিকস

2
@ ক্রিসকিরিকস ডেকরেটারটি @FunctionalInterfaceমূলত কেবলমাত্র ডকুমেন্টেশনের উদ্দেশ্যে, কারণ সংকলকটি একক বিমূর্ত পদ্ধতিতে যে কোনও ইন্টারফেসের সাথে আনন্দের সাথে এটি করতে পারে।
ভুল কাজ

117

Comparatorএকটি কার্যকরী ইন্টারফেস , এবং Integer::maxসেই ইন্টারফেসের সাথে সম্মতি জানায় (অটোবক্সিং / আনবক্সিংয়ের বিষয়টি বিবেচনার পরে)। এটি দুটি intমান গ্রহণ করে এবং একটিটি প্রদান করে int- যেমনটি আপনি প্রত্যাশা করতেন Comparator<Integer>(আবার, পূর্ণসংখ্যা / int পার্থক্য উপেক্ষা করার জন্য স্কুইন্টিং)।

যাইহোক, আমি এটা সঠিক জিনিস দেওয়া যে কি আশা করবেন না Integer.maxমেনে চলছে না শব্দার্থবিদ্যা এর Comparator.compare। এবং সত্যই এটি সাধারণভাবে কাজ করে না। উদাহরণস্বরূপ, একটি ছোট পরিবর্তন করুন:

for (int i = 1; i <= 20; i++)
    list.add(-i);

... এবং এখন maxমান -20 এবং minমান -1।

পরিবর্তে, উভয় কল ব্যবহার করা উচিত Integer::compare:

System.out.println(list.stream().max(Integer::compare).get());
System.out.println(list.stream().min(Integer::compare).get());

1
আমি কার্যকরী ইন্টারফেস সম্পর্কে জানি; এবং আমি জানি কেন এটি ভুল ফলাফল দেয়। আমি কেবল আশ্চর্য হয়েছি যে পৃথিবীতে
সংকলকটি

6
@ ফিজ: আচ্ছা আপনি যে আনবক্সিং সম্পর্কে অস্পষ্ট ছিলেন তা কি ছিল? (আমি ঠিক যে অংশ মধ্যে লাগছিল না।) একজন Comparator<Integer>হবে int compare(Integer, Integer)... এটা মন boggling এর না যে জাভা একটি পদ্ধতির রেফারেন্স দেয় int max(int, int)যে রূপান্তর ...
জন স্কিট

7
@fge: সংকলকটির শব্দার্থ সম্পর্কে জানা উচিত Integer::max? এর দৃষ্টিকোণ থেকে আপনি কোনও ফাংশনে গিয়েছেন যা এর স্পেসিফিকেশনটির সাথে মেলে, এটিই সত্যিকার অর্থে চলতে পারে।
মার্ক পিটার্স

6
@fge: বিশেষত, যদি আপনি কী চলছে তার একটি অংশ বুঝতে পারছেন , তবে এর একটি নির্দিষ্ট দিক সম্পর্কে আগ্রহী হন, তবে আপনার ইতিমধ্যে জানা বিটগুলি ব্যাখ্যা করে লোকেরা তাদের সময় নষ্ট করা এড়াতে এই প্রশ্নটিতে এটি স্পষ্ট করে তোলা উচিত।
জন স্কিটি

20
আমি মনে করি অন্তর্নিহিত সমস্যাটি হ'ল ধরণের স্বাক্ষর Comparator.compare। এটি একটি ফেরত পাঠাবেন enumএর {LessThan, GreaterThan, Equal}, কোনো int। এইভাবে, কার্যকরী ইন্টারফেসটি আসলে মিলবে না এবং আপনি একটি সংকলন ত্রুটি পাবেন। আইওডাব্লু: টাইপের স্বাক্ষর Comparator.compareদুটি বস্তুর তুলনা করার অর্থ কীভাবে শব্দার্থকে ক্যাপচার করে না, এবং এইভাবে অন্য ইন্টারফেসগুলির সাথে তুলনামূলকভাবে বস্তুর তুলনা করার মতো কিছুই নেই যা ঘটনাক্রমে একই ধরণের স্বাক্ষর রাখে।
Jörg ডব্লু মিত্তাগ

19

এটি কাজ করে কারণ ইন্টারফেসের Integer::minএকটি প্রয়োগের সমাধান করে Comparator<Integer>

সমাধানের Integer::minসমাধান পদ্ধতির রেফারেন্সটি এর Integer.min(int a, int b)সমাধান করে IntBinaryOperator, এবং সম্ভবত অটোবক্সিং কোথাও এটিকে একটি করে তোলে BinaryOperator<Integer>

আর min()রেস্প max()পদ্ধতি Stream<Integer>জিজ্ঞাসা Comparator<Integer>ইন্টারফেস বাস্তবায়িত করতে হবে।
এখন এটি একক পদ্ধতিতে সমাধান হয় Integer compareTo(Integer o1, Integer o2)। যা টাইপ BinaryOperator<Integer>

উভয় পদ্ধতি হ'ল এবং এইভাবে ম্যাজিকটি ঘটেছে BinaryOperator<Integer>


এটা তোলে অর্থাৎ সম্পূর্ণভাবে সঠিক নয় Integer::minকার্যকরী Comparable। এটি এমন কিছু নয় যা কোনও কিছুর প্রয়োগ করতে পারে। তবে এটি কার্যকর করে এমন কোনও অবজেক্টে মূল্যায়ন করা হয় Comparable
লি

1
@ লিআই ধন্যবাদ, আমি এখনই এটি ঠিক করেছি।
স্কিভি

Comparator<Integer>একক-বিমূর্ত-পদ্ধতি (ওরফে "ফাংশনাল") ইন্টারফেস, এবং Integer::minএটির চুক্তিটি পূর্ণ করে, তাই ল্যাম্বডাকে এটি ব্যাখ্যা করা যায়। আমি জানি না আপনি কীভাবে এখানে বাইনারি অপারেটরটিকে খেলতে আসতে দেখছেন (বা ইনটাইনারিওপ্রেটর, হয়) - এটির তুলনাকারীর মধ্যে কোনও সাব-টাইপিং সম্পর্ক নেই।
পাওলো ইবারম্যান

2

এছাড়াও ডেভিড এম লয়েড এক করে দেওয়া তথ্য থেকে যুক্ত করতে পারে যে প্রক্রিয়া এই বলা হয় অনুমতি দেয় লক্ষ্য টাইপিং

ধারণাটি এই যে সংকলকটি ল্যাম্বডা এক্সপ্রেশন বা কোনও পদ্ধতির রেফারেন্সগুলিতে নির্ধারিত টাইপটি কেবলমাত্র অভিব্যক্তির উপর নির্ভর করে না, যেখানে এটি ব্যবহৃত হয় তার উপরও নির্ভর করে।

একটি এক্সপ্রেশনের লক্ষ্য হল সেই পরিবর্তনশীল যা এর ফলাফল নির্ধারিত হয় বা যে পরামিতিটিতে তার ফলাফলটি পাস হয়।

লাম্বদা এক্সপ্রেশন এবং পদ্ধতির রেফারেন্সগুলিকে এমন একটি টাইপ দেওয়া হয়েছে যা তাদের টার্গেটের সাথে মিলে যায়, যদি এই ধরণের কোনও সন্ধান পাওয়া যায়।

দেখুন প্রকার ইনফিরেনস অধ্যায় আরও তথ্যের জন্য জাভা টিউটোরিয়াল-এ।


1

একটি অ্যারে সর্বোচ্চ এবং মিনিট পেয়ে আমার একটি ত্রুটি হয়েছিল তাই আমার সমাধানটি ছিল:

int max = Arrays.stream(arrayWithInts).max().getAsInt();
int min = Arrays.stream(arrayWithInts).min().getAsInt();
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.