CodeGym /Blog Jawa /Acak /Antarmuka Comparator Jawa
John Squirrels
tingkat
San Francisco

Antarmuka Comparator Jawa

Diterbitake ing grup
Wong kesed ora mung nulis bab Komparator lan bandhingan ing Jawa. Aku ora kesed, dadi mangga tresna lan gripe babagan panjelasan liyane. Mugi iku ora bakal superfluous. Lan ya, artikel iki minangka jawaban kanggo pitakonan: " Apa sampeyan bisa nulis komparator saka memori? " Muga-muga kabeh wong bisa nulis komparator saka memori sawise maca artikel iki. Antarmuka Javas Comparator - 1

Pambuka

Kaya sing wis dingerteni, basa Jawa minangka basa sing berorientasi obyek. Akibaté, adat kanggo ngapusi obyek ing Jawa. Nanging cepet utawa mengko, sampeyan ngadhepi tugas mbandhingake obyek adhedhasar sawetara karakteristik. Contone : Upaminipun kita duwe sawetara pesen sing diterangake dening Messagekelas:

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;
    }
}
Sijine kelas iki ing Tutorialspoint Java compiler . Aja lali nambahake pernyataan impor uga:

import java.util.Random;
import java.util.ArrayList;
import java.util.List;
Ing maincara, nggawe sawetara pesen:

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);
}
Ayo dipikirake apa sing bakal ditindakake yen kita pengin mbandhingake? Contone, kita pengin ngurutake miturut id. Lan kanggo nggawe urutan, kita kudu piye wae mbandhingake obyek supaya bisa ngerti obyek sing kudu luwih dhisik (yaiku sing luwih cilik) lan endi sing kudu ditindakake (yaiku sing luwih gedhe). Ayo dadi miwiti karo kelas kaya java.lang.Object . Kita ngerti yen kabeh kelas kanthi implisit entuk warisan Objectkelas kasebut. Lan iki ndadekake pangertèn amarga nuduhake konsep sing "kabeh iku obyek" lan menehi prilaku umum kanggo kabeh kelas. Kelas iki nyatakake yen saben kelas duwe rong metode: → hashCode Metode hashCodengasilake sawetara numerik (int) representasi saka obyek. Apa tegese? Iku tegese yen sampeyan nggawe rong kedadean beda saka kelas, banjur padha kudu beda hashCodes. Katrangan cara kasebut ujar: "Minangka praktis, metode hashCode sing ditetepake dening Obyek kelas ngasilake integer sing béda kanggo obyek sing béda". Ing tembung liyane, kanggo rong beda instances, kudu ana beda hashCodes. Tegese, cara iki ora cocok kanggo perbandingan kita. → equals. Cara equalsnjawab pitakonan "apa obyek iki padha?" lan ngasilake boolean." Secara default, metode iki nduweni kode ing ngisor iki:

public boolean equals(Object obj) {
    return (this == obj);
}
Sing, yen cara iki ora overridden, iku ateges ngandika apa referensi obyek cocog utawa ora. Iki dudu sing dikarepake kanggo pesen kita, amarga kita kasengsem ing id pesen, dudu referensi obyek. Lan sanajan kita ngilangi equalsmetode kasebut, sing paling bisa kita ngarepake yaiku sinau manawa padha. Lan iki ora cukup kanggo kita nemtokake urutane. Dadi apa sing kita butuhake? We kudu soko sing mbandhingaké. Sing mbandhingake yaiku a Comparator. Bukak Java API lan golek Comparator . Pancen, ana java.util.Comparatorantarmuka java.util.Comparator and java.util.Comparable Kaya sing sampeyan ngerteni, antarmuka kasebut ana. A kelas sing ngleksanakake ngandika, "Aku ngleksanakake cara sing mbandhingaké obyek." Siji-sijine sing sampeyan kudu eling yaiku kontrak komparator, sing ditulis kaya ing ngisor iki:

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
Saiki ayo nulis komparator. Kita kudu ngimpor java.util.Comparator. Sawise statement ngimpor, nambah ing ngisor iki kanggo maincara: Comparator<Message> comparator = new Comparator<Message>(); Mesthi, iki ora bisa, amarga Comparatorantarmuka. Dadi kita nambah kurung kriting {}sawise kurung. Tulis cara ing ngisor iki ing jero braces:

public int compare(Message o1, Message o2) {
    return o1.getId().compareTo(o2.getId());
}
Sampeyan malah ora perlu ngelingi ejaan. Komparator yaiku wong sing nindakake perbandingan, yaiku mbandhingake. Kanggo nuduhake urutan relatif saka obyek, kita bali int. Sejatine iku. Apik lan gampang. Nalika sampeyan bisa ndeleng saka conto, saliyane Comparator, ana antarmuka liyane — java.lang.Comparable, kang mbutuhake kita ngleksanakake compareTocara. Antarmuka iki ngandika, "kelas sing ngleksanakake kula ndadekake iku bisa kanggo mbandhingaké kedadean saka kelas." Contone, Integerimplementasine saka compareTo kaya ing ngisor iki:

(x < y) ? -1 : ((x == y) ? 0 : 1)
Java 8 ngenalaken sawetara owah-owahan becik. Yen sampeyan ndeleng antarmuka kanthi luwih cetha Comparator, sampeyan bakal weruh @FunctionalInterfaceanotasi ing ndhuwur. Anotasi iki kanggo tujuan informasi lan ngandhani yen antarmuka iki fungsional. Iki tegese antarmuka iki mung nduweni 1 metode abstrak, yaiku metode tanpa implementasine. Apa iki menehi kita? Saiki kita bisa nulis kode komparator kaya iki:

Comparator<Message> comparator = (o1, o2) -> o1.getId().compareTo(o2.getId());
Kita jeneng variabel ing kurung. Jawa bakal weruh amarga mung ana siji cara, banjur nomer sing dibutuhake lan jinis paramèter input cetha. Banjur kita nggunakake operator panah kanggo pass menyang bagean kode iki. Apa maneh, thanks kanggo Java 8, saiki kita duwe metode standar ing antarmuka. Cara iki katon minangka standar nalika kita ngleksanakake antarmuka. Antarmuka Comparatorwis sawetara. Tuladhane:

Comparator moreImportant = Comparator.reverseOrder();
Comparator lessImportant = Comparator.naturalOrder();
Ana cara liya sing bakal nggawe kode luwih resik. Deleng conto ing ndhuwur, ing ngendi kita nemtokake komparator kita. Apa sing ditindakake? Iku cukup primitif. Iku mung njupuk obyek lan ngekstrak sawetara nilai sing "sebanding". Contone, Integerngleksanakake comparable, supaya kita bisa nindakake operasi compareTo ing nilai kolom id pesen. Fungsi komparator prasaja iki bisa ditulis kaya mangkene:

Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
Ing tembung liyane, kita duwe Comparatorsing mbandhingaké kaya iki: njupuk obyek, nggunakake getId()cara kanggo njaluk Comparablesaka wong-wong mau, lan banjur digunakake compareTokanggo mbandhingaké. Lan ora ana konstruksi sing luwih nggegirisi. Lan pungkasane, aku pengin nyathet siji fitur liyane. Komparator bisa dirantai. Tuladhane:

Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
comparator = comparator.thenComparing(obj -> obj.getMessage().length());

Aplikasi

Nyatakake komparator ternyata cukup logis, apa sampeyan mikir? Saiki kita kudu ndeleng carane lan ing ngendi nggunakake. → Collections.sort(java.util.Collections) Kita bisa, mesthi, ngurutake koleksi kanthi cara iki. Nanging ora saben koleksi, mung dhaptar. Ora ana sing ora biasa ing kene, amarga dhaptar minangka jinis koleksi sing sampeyan ngakses unsur miturut indekse. Iki ngidini unsur kapindho diganti karo unsur katelu. Mulane cara ngurutake ing ngisor iki mung kanggo dhaptar:

Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
Collections.sort(messages, comparator);
Arrays.sort(java.util.Arrays) Array uga gampang diurutake. Maneh, kanthi alasan sing padha - unsur kasebut diakses kanthi indeks. → Descendants of java.util.SortedSet and java.util.SortedMap Sampeyan bakal kelingan Setlan Mapora njamin supaya unsur disimpen. Nanging, kita duwe implementasi khusus sing njamin pesenan kasebut. Lan yen unsur koleksi ora dileksanakake java.util.Comparable, banjur kita bisa ngirim Comparatormenyang konstruktor:

Set<Message> msgSet = new TreeSet(comparator);
Stream API Ing Stream API, sing muncul ing Java 8, komparator ngidini sampeyan nyederhanakake karya karo unsur stream. Contone, umpamane kita butuh urutan nomer acak saka 0 nganti 999, kalebu:

Supplier<Integer> randomizer = () -> new Random().nextInt(1000);
Stream.generate(randomizer)
    .limit(10)
    .sorted(Comparator.naturalOrder())
    .forEach(e -> System.out.println(e));
Kita bisa mandheg ing kene, nanging ana masalah sing luwih menarik. Contone, Upaminipun sampeyan kudu nyiyapake a Map, ngendi tombol iku id pesen. Kajaba iku, kita pengin ngurutake kunci kasebut, mula kita bakal miwiti nganggo kode ing ngisor iki:

Map<Integer, Message> collected = Arrays.stream(messages)
                .sorted(Comparator.comparing(msg -> msg.getId()))
                .collect(Collectors.toMap(msg -> msg.getId(), msg -> msg));
Kita bener njaluk HashMapkene. Lan kita ngerti, iku ora njamin pesenan sembarang. Akibaté, unsur kita, sing diurutake miturut id, mung ilang urutane. Ora apik. Kita kudu ngganti kolektor kita:

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));
Kode kasebut wiwit katon rada medeni, nanging saiki masalah wis ditanggulangi kanthi bener. Waca liyane babagan macem-macem klompok ing kene: Sampeyan bisa nggawe kolektor dhewe. Waca liyane kene: "Nggawe kolektor adat ing Jawa 8" . Lan sampeyan bakal entuk manfaat saka maca diskusi ing kene: "Dhaptar Java 8 kanggo peta nganggo stream" .

Tiba-trap

Comparatorlan Comparableapik. Nanging ana siji nuansa sing kudu sampeyan eling. Nalika kelas nindakake ngurutake, ngarepake kelas sampeyan bisa diowahi dadi Comparable. Yen ora, sampeyan bakal nampa kesalahan nalika mbukak. Ayo katon ing conto:

SortedSet<Message> msg = new TreeSet<>();
msg.add(new Message(2, "Developer".getBytes()));
Kayane ora ana sing salah ing kene. Nanging nyatane, ing conto kita, bakal gagal karo kesalahan: java.lang.ClassCastException: Message cannot be cast to java.lang.Comparable Lan kabeh amarga nyoba ngurutake unsur (iku SortedSet, sawise kabeh) ... nanging ora bisa. Aja lali iki nalika nggarap SortedMaplan SortedSet.

Wacan liyane:

Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION