CodeGym /جاوا بلاگ /Random-SD /جاوا جي Comparator انٽرفيس
John Squirrels
سطح
San Francisco

جاوا جي Comparator انٽرفيس

گروپ ۾ شايع ٿيل
سست صرف اهي ئي نه آهن جيڪي جاوا ۾ Comparators ۽ comparisons بابت لکن ٿا. مان سست نه آهيان، تنهنڪري مهرباني ڪري پيار ۽ گرفت اڃا تائين هڪ ٻي وضاحت بابت. مون کي اميد آهي ته اهو اضافي نه ٿيندو. ۽ ها، هي مضمون ان سوال جو جواب آهي ته: ” ڇا توهان ياداشت مان ڪامپيٽرٽر لکي سگهو ٿا؟ “ مون کي اميد آهي ته هرڪو هن مضمون پڙهڻ کان پوءِ ياداشت مان ڪامپيٽرٽر لکي سگهندو. Javas Comparator انٽرفيس - 1

تعارف

جئين توهان ڄاڻو ٿا، جاوا هڪ اعتراض تي مبني ٻولي آهي. نتيجي طور، جاوا ۾ شين کي ترتيب ڏيڻ لاء رواج آهي. پر جلدي يا بعد ۾، توهان کي ڪجهه خاصيتن جي بنياد تي شين جي مقابلي جي ڪم کي منهن ڏيڻو پوندو. مثال طور : فرض ڪريو اسان وٽ ڪلاس پاران بيان ڪيل ڪجهه پيغام آهن Message:
public static class Message {
    private String message;
    private int id;

    public Message(String message) {
        this.message = message;
        this.id = new Random().nextInt(1000);
    }
    public String getMessage() {
        return message;
    }
    public Integer getId() {
        return id;
    }
    public String toString() {
        return "[" + id + "] " + message;
    }
}
ھن ڪلاس کي Tutorialspoint Java compiler ۾ رکو . درآمد جي بيانن کي پڻ شامل ڪرڻ نه وساريو:
import java.util.Random;
import java.util.ArrayList;
import java.util.List;
طريقي ۾ main، ڪيترائي پيغام ٺاھيو:
public static void main(String[] args){
    List<Message> messages = new ArrayList();
    messages.add(new Message("Hello, World!"));
    messages.add(new Message("Hello, Sun!"));
    System.out.println(messages);
}
اچو ته سوچيون ته جيڪڏهن اسان انهن جو مقابلو ڪرڻ چاهيون ته ڇا ڪنداسين؟ مثال طور، اسان id ذريعي ترتيب ڏيڻ چاهيون ٿا. ۽ هڪ آرڊر ٺاهڻ لاءِ، اسان کي ڪنهن نه ڪنهن طرح شين جو مقابلو ڪرڻو پوندو ته اهو سمجهڻ لاءِ ته ڪهڙي شئي کي پهرين اچڻ گهرجي (يعني ننڍي کي) ۽ ڪهڙي کي پٺيان اچڻ گهرجي (يعني وڏو). اچو ته هڪ ڪلاس سان شروع ڪريون جهڙوڪ java.lang.Object . اسان ڄاڻون ٿا ته سڀئي طبقن کي Objectطبقاتي طور تي ورثي ۾ ورثي ۾. ۽ اهو سمجھ ۾ اچي ٿو ڇاڪاڻ ته اهو تصور کي ظاهر ڪري ٿو ته "هر شي هڪ اعتراض آهي" ۽ سڀني طبقن لاء عام رويي مهيا ڪري ٿي. هي طبقو حڪم ڏئي ٿو ته هر طبقي جا ٻه طريقا آهن: → hashCode طريقو hashCodeڪجهه عددي ( int) اعتراض جي نمائندگي ڪري ٿو. هن جو مطلب ڇا آهي؟ ان جو مطلب اهو آهي ته جيڪڏهن توهان هڪ طبقي جا ٻه مختلف مثال ٺاهيندا آهيو، پوء انهن کي مختلف هجڻ گهرجي hashCode. طريقي جي وضاحت گهڻو ڪري چوي ٿو: "جيترو وڌيڪ معقول طور تي عملي آهي، هيش ڪوڊ جو طريقو ڪلاس آبجیکٹ پاران بيان ڪيل مختلف شين لاءِ الڳ الڳ عدد واپس ڪندو آهي". ٻين لفظن ۾، ٻن مختلف instances لاء، اتي مختلف هجڻ گهرجي hashCode. اهو آهي، هي طريقو اسان جي مقابلي لاء مناسب ناهي. → equals. طريقو equalsسوال جو جواب ڏئي ٿو "ڇا اهي شيون برابر آهن؟" ۽ موٽائي ٿو a boolean." ڊفالٽ طور، هن طريقي ۾ هيٺ ڏنل ڪوڊ آهي:
public boolean equals(Object obj) {
    return (this == obj);
}
اهو آهي، جيڪڏهن اهو طريقو ختم نه ڪيو ويو آهي، اهو لازمي طور تي چوي ٿو ته اعتراض جو حوالو ملندو يا نه. اهو نه آهي جيڪو اسان پنهنجي پيغامن لاءِ چاهيون ٿا، ڇاڪاڻ ته اسان کي پيغام جي سڃاڻپ ۾ دلچسپي آهي، اعتراض جي حوالي سان نه. ۽ جيتوڻيڪ جيڪڏهن اسان equalsطريقي کي ختم ڪريون ٿا، اسان سڀ کان وڌيڪ اميد ڪري سگهون ٿا ته اهو سکڻ لاء ته ڇا اهي برابر آهن. ۽ اهو اسان لاءِ آرڊر طئي ڪرڻ لاءِ ڪافي ناهي. پوء اسان کي ڇا گهرجي؟ اسان کي ڪجھ جي ضرورت آھي جيڪو موازنہ ڪري. جيڪو مقابلو ڪري ٿو اهو هڪ آهي Comparator. Java API کوليو ۽ ڳولھيو Comparator . درحقيقت، اتي ھڪڙو java.util.Comparatorانٽرفيس آھي java.util.Comparator and java.util.Comparable جيئن توھان ڏسي سگھو ٿا، ھڪڙو انٽرفيس موجود آھي. ھڪڙو طبقو جيڪو ان کي لاڳو ڪري ٿو چوي ٿو، "مان ھڪڙو طريقو لاڳو ڪري ٿو جيڪو شين جي مقابلي ۾." صرف هڪ ئي شيء جيڪا توهان کي ياد رکڻ جي ضرورت آهي موازنہ ڪندڙ معاهدو، جنهن جو اظهار هن ريت ڪيو ويو آهي:

Comparator returns an int according to the following rules: 
  • It returns a negative int if the first object is smaller
  • It returns a positive int if the first object is larger
  • It returns zero if the objects are equal
هاڻي اچو ته هڪ comparator لکون. اسان کي درآمد ڪرڻو پوندو java.util.Comparator. درآمد واري بيان کان پوء، طريقي سان ھيٺيون شامل ڪريو main: Comparator<Message> comparator = new Comparator<Message>(); يقينا، اھو ڪم نه ڪندو، ڇو جو Comparatorھڪڙو انٽرفيس آھي. {}تنهن ڪري اسان قوس کان پوء گهڙيل ڪنگڻ شامل ڪندا آهيون . هيٺيون طريقو لکو braces اندر:
public int compare(Message o1, Message o2) {
    return o1.getId().compareTo(o2.getId());
}
توهان کي اسپيلنگ ياد ڪرڻ جي ضرورت ناهي. هڪ موازنہ ڪندڙ اهو آهي جيڪو هڪ مقابلي کي انجام ڏئي ٿو، اهو آهي، اهو مقابلو ڪري ٿو. شين جي لاڳاپي واري ترتيب کي ظاهر ڪرڻ لاء، اسان واپس ڪريون ٿا هڪ int. اهو بنيادي طور تي آهي. سٺو ۽ آسان. جيئن ته توهان مثال مان ڏسي سگهو ٿا، Comparator کان علاوه، هڪ ٻيو انٽرفيس آهي - java.lang.Comparable، جيڪو اسان کي compareToطريقو لاڳو ڪرڻ جي ضرورت آهي. هي انٽرفيس چوي ٿو، "هڪ ڪلاس جيڪو مون کي لاڳو ڪري ٿو اهو ممڪن بڻائي ٿو ڪلاس جي مثالن جو مقابلو ڪرڻ." مثال طور، Integer'To جو عمل compareھيٺ ڏنل آھي:
(x < y) ? -1 : ((x == y) ? 0 : 1)
جاوا 8 ڪجهه سٺيون تبديليون متعارف ڪرايو. جيڪڏهن توهان انٽرفيس تي هڪ ويجهي نظر وٺو Comparator، توهان ان جي مٿان تشريح ڏسندا @FunctionalInterface. هي تشريح معلومات جي مقصدن لاءِ آهي ۽ اسان کي ٻڌائي ٿي ته هي انٽرفيس ڪم ڪندڙ آهي. هن جو مطلب آهي ته هن انٽرفيس ۾ صرف 1 خلاصو طريقو آهي، جيڪو هڪ طريقو آهي بغير ڪنهن عمل جي. هي اسان کي ڇا ڏئي ٿو؟ هاڻي اسان موازنہ ڪندڙ ڪوڊ هن طرح لکي سگهون ٿا:
Comparator<Message> comparator = (o1, o2) -> o1.getId().compareTo(o2.getId());
اسان variables کي قوس ۾ نالو ڏيون ٿا. جاوا ڏسندو ته ڇاڪاڻ ته اتي صرف هڪ طريقو آهي، پوء گهربل نمبر ۽ قسم جا ان پٽ پيٽرولر واضح آهن. پوءِ اسان تير آپريٽر استعمال ڪريون ٿا انھن کي ڪوڊ جي ھن حصي ڏانھن منتقل ڪرڻ لاءِ. وڌيڪ ڇا آهي، جاوا 8 جي مهرباني، اسان وٽ هاڻي انٽرفيس ۾ ڊفالٽ طريقا آهن. اهي طريقا ڊفالٽ طور ظاهر ٿيندا آهن جڏهن اسان هڪ انٽرفيس کي لاڳو ڪندا آهيون. انٽرفيس Comparatorڪيترن ئي آهي. مثال طور:
Comparator moreImportant = Comparator.reverseOrder();
Comparator lessImportant = Comparator.naturalOrder();
ھڪڙو ٻيو طريقو آھي جيڪو توھان جو ڪوڊ صاف ڪندو. مٿي ڏنل مثال تي هڪ نظر وٺو، جتي اسان اسان جي مقابلي جي وضاحت ڪئي. اهو ڇا ٿو ڪري؟ اهو ڪافي ابتدائي آهي. اهو صرف هڪ اعتراض وٺندو آهي ۽ ڪجهه قدر ڪڍي ٿو جيڪو "مقابلي" آهي. مثال طور، Integerلاڳو ڪري ٿو comparable، تنهنڪري اسان هڪ compareTo آپريشن ڪرڻ جي قابل آهيون پيغام جي id فيلڊ جي قدرن تي. هن سادي comparator فعل هن طرح لکي سگهجي ٿو:
Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
ٻين لفظن ۾، اسان وٽ ھڪڙو آھي Comparatorجيڪو ھن طرح موازنہ ڪري ٿو: اھو شيون وٺندو آھي، انھن مان getId()حاصل ڪرڻ لاء طريقو استعمال ڪندو آھي، ۽ پوء موازنہ ڪرڻ لاء استعمال ڪندو آھي. ۽ نه وڌيڪ خوفناڪ تعميرات آهن. ۽ آخر ۾، مان هڪ وڌيڪ خصوصيت نوٽ ڪرڻ چاهيان ٿو. Comparators زنجيرن ڪري سگهجي ٿو. مثال طور: ComparablecompareTo
Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
comparator = comparator.thenComparing(obj -> obj.getMessage().length());

درخواست

هڪ مقابلي جو اعلان ڪرڻ بلڪل منطقي آهي، ڇا توهان سوچيو ٿا؟ هاڻي اسان کي ڏسڻ جي ضرورت آهي ته ان کي ڪيئن ۽ ڪٿي استعمال ڪجي. → Collections.sort(java.util.Collections) اسان، يقينا، هن طريقي سان مجموعن کي ترتيب ڏئي سگهون ٿا. پر هر مجموعو نه، صرف فهرستون. هتي ڪجھ به غير معمولي نه آهي، ڇاڪاڻ ته فهرستون مجموعن جو قسم آهن جتي توهان انهن جي انڊيڪس ذريعي عناصر تائين رسائي ڪندا آهيو. هي ٻئي عنصر کي ٽئين عنصر سان تبديل ڪرڻ جي اجازت ڏئي ٿو. تنهن ڪري ترتيب ڏيڻ جو هيٺ ڏنل طريقو صرف فهرستن لاءِ آهي:
Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
Collections.sort(messages, comparator);
Arrays.sort(java.util.Arrays) Arrays پڻ ترتيب ڏيڻ آسان آهن. ٻيهر، ساڳئي سبب لاء - انهن جا عنصر انڊيڪس ذريعي پهچندا آهن. → Descendants of java.util.SortedSet and java.util.SortedMap توهان اهو ياد ڪندا Set۽ Mapان حڪم جي ضمانت نه ڏيو جنهن ۾ عناصر محفوظ ٿيل آهن. پر، اسان وٽ خاص عمل آهن جيڪي آرڊر جي ضمانت ڏين ٿيون. ۽ جيڪڏهن هڪ مجموعو جا عنصر لاڳو نٿا ڪن java.util.Comparable، ته پوءِ اسان ان جي تعمير ڪندڙ ڏانهن منتقل ڪري سگهون ٿا Comparator:
Set<Message> msgSet = new TreeSet(comparator);
Stream API اسٽريم API ۾، جيڪو جاوا 8 ۾ ظاهر ٿيو، مقابلو ڪندڙ توهان کي اسٽريم عناصر سان ڪم کي آسان ڪرڻ جي اجازت ڏين ٿا. مثال طور، فرض ڪريو اسان کي 0 کان 999 تائين بي ترتيب نمبرن جي هڪ ترتيب جي ضرورت آهي، جنهن ۾ شامل آهي:
Supplier<Integer> randomizer = () -> new Random().nextInt(1000);
Stream.generate(randomizer)
    .limit(10)
    .sorted(Comparator.naturalOrder())
    .forEach(e -> System.out.println(e));
اسان هتي روڪي سگهون ٿا، پر اڃا به وڌيڪ دلچسپ مسئلا آهن. مثال طور، فرض ڪريو ته توهان کي تيار ڪرڻ جي ضرورت آهي هڪ Map، جتي ڪيچي هڪ پيغام جي سڃاڻپ آهي. اضافي طور تي، اسان انهن ڪنجين کي ترتيب ڏيڻ چاهيون ٿا، تنهنڪري اسان هيٺ ڏنل ڪوڊ سان شروع ڪنداسين:
Map<Integer, Message> collected = Arrays.stream(messages)
                .sorted(Comparator.comparing(msg -> msg.getId()))
                .collect(Collectors.toMap(msg -> msg.getId(), msg -> msg));
اسان اصل ۾ HashMapهتي حاصل ڪريون ٿا. ۽ جيئن اسان ڄاڻون ٿا، اهو ڪنهن به حڪم جي ضمانت نٿو ڏئي. نتيجي طور، اسان جا عناصر، جيڪي id جي ترتيب سان ترتيب ڏنل هئا، بس پنهنجو آرڊر وڃائي ٿو. سٺو ناهي. اسان کي اسان جي ڪليڪٽر کي ٿورو تبديل ڪرڻو پوندو:
Map<Integer, Message> collected = Arrays.stream(messages)
                .sorted(Comparator.comparing(msg -> msg.getId()))
                .collect(Collectors.toMap(msg -> msg.getId(), msg -> msg, (oldValue, newValue) -> oldValue, TreeMap::new));
ڪوڊ ٿورو خوفناڪ ڏسڻ شروع ڪيو آهي، پر هاڻي اهو مسئلو صحيح طور تي حل ڪيو ويو آهي. هتي مختلف گروپن بابت وڌيڪ پڙهو: توهان پنهنجو ڪليڪٽر ٺاهي سگهو ٿا. وڌيڪ پڙهو هتي: "جاوا 8 ۾ ڪسٽم ڪليڪٽر ٺاهڻ" . ۽ توهان هتي بحث پڙهڻ مان فائدو حاصل ڪندا: "جاوا 8 لسٽ سان نقشي سان گڏ" .

ڦاسي پوڻ

Comparator۽ Comparableسٺا آهن. پر اتي ھڪڙو nuance آھي توھان کي ياد رکڻ گھرجي. جڏهن هڪ ڪلاس ترتيب ڏئي ٿو، اهو توقع ڪري ٿو ته توهان جو ڪلاس هڪ ۾ تبديل ٿي سگهي ٿو Comparable. جيڪڏهن اهو معاملو نه آهي، ته پوء توهان رن ٽائيم تي هڪ غلطي وصول ڪندا. اچو ته هڪ مثال ڏسو:
SortedSet<Message> msg = new TreeSet<>();
msg.add(new Message(2, "Developer".getBytes()));
اهو لڳي ٿو ته هتي ڪجھ به غلط ناهي. پر حقيقت ۾، اسان جي مثال ۾، اهو هڪ غلطي سان ناڪام ٿيندو: java.lang.ClassCastException: Message cannot be cast to java.lang.Comparable ۽ سڀ ڪجهه ڇاڪاڻ ته اهو عناصر کي ترتيب ڏيڻ جي ڪوشش ڪئي (اهو آهي SortedSet، سڀ کان پوء) ... پر نه ٿي سگهيو. اهو نه وساريو جڏهن ڪم ڪري رهيو آهي SortedMap۽ SortedSet.
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION