Programátori musia často triediť prvky z databázy do kolekcie, poľa alebo mapy. V Jave môžeme implementovať akýkoľvek triediaci algoritmus, ktorý chceme, s akýmkoľvek typom. Pomocou Porovnateľné
rozhranie a porovnať s()
metódou môžeme triediť podľa abecedného poradia, String
dĺžka, obrátené abecedné poradie alebo čísla. The Komparátor
Rozhranie nám umožňuje robiť to isté, ale flexibilnejším spôsobom.
Čokoľvek chceme urobiť, musíme len vedieť, ako implementovať správnu logiku triedenia pre dané rozhranie a typ.
Získajte zdrojový kód
Získajte kód pre tento Java Challenger. Podľa príkladov môžete spustiť svoje vlastné testy.
Triedenie zoznamu Java List s vlastným objektom
Pre náš príklad použijeme rovnaký POJO, aký sme doteraz používali pre iných Java Challengerov. V tomto prvom príklade implementujeme porovnateľné rozhranie v Simpson
triedy, pomocou Simpson
v generickom type:
trieda Simpson implementuje Comparable {Názov reťazca; Simpson (názov reťazca) {this.name = meno; } @Override public int compareTo (Simpson simpson) {return this.name.compareTo (simpson.name); }} public class SimpsonSorting {public static void main (String ... sortingWithList) {List simpsons = new ArrayList (); simpsons.add (nový SimpsonCharacter ("Homer")); simpsons.add (nový SimpsonCharacter („Marge“)); simpsons.add (nový SimpsonCharacter („Bart“)); simpsons.add (nový SimpsonCharacter ("Lisa")); Zbierka.trieda (simpsonovci); simpsons.stream (). map (s -> s.name) .forEach (System.out :: print); Zbierky.Reverzný (Simpsonovi); simpsons.stream (). forEach (System.out :: print); }}
Upozorňujeme, že sme prepísali metódu compareTo () a odovzdali sme inú Simpson
objekt. Tiež sme prepísali natiahnuť()
metóda, len aby sa príklad ľahšie čítal.
The natiahnuť
metóda zobrazuje všetky informácie z objektu. Keď objekt vytlačíme, výstupom bude všetko, v čom bol implementovaný natiahnuť()
.
Metóda compareTo ()
The porovnať s()
metóda porovnáva daný objekt alebo aktuálnu inštanciu so zadaným objektom a určuje tak poradie objektov. Tu je rýchly pohľad na to, ako porovnať s()
Tvorba:
Ak sa porovnanie vráti | Potom ... |
| |
| |
| |
Môžeme použiť iba triedy, ktoré sú porovnateľné s sort ()
metóda. Ak sa pokúsime prejsť a Simpson
ktoré sa nerealizuje Porovnateľné
, dostaneme chybu kompilácie.
The sort ()
metóda využíva polymorfizmus odovzdaním ľubovoľného objektu, ktorý je Porovnateľné
. Objekty sa potom zoradia podľa očakávania.
Výstup z predchádzajúceho kódu by bol:
Bart Homer Lisa Marge
Ak by sme chceli obrátiť poradie, mohli by sme vymeniť sort ()
pre reverz ()
; od:
Zbierka.trieda (simpsonovci);
do:
Zbierky.Reverzný (Simpsonovci);
Nasadzovanie reverz ()
metóda zmení predchádzajúci výstup na:
Marge Lisa Homer Bart
Triedenie poľa Java
V Jave môžeme triediť pole s akýmkoľvek typom, ktorý chceme, pokiaľ implementuje Porovnateľné
rozhranie. Tu je príklad:
public class ArraySorting {public static void main (String ... moeTavern) {int [] moesPints = new int [] {9, 8, 7, 6, 1}; Arrays.sort (moesPints); Arrays.stream (moesPints) .forEach (System.out :: print); Simpson [] simpsons = nový Simpson [] {nový Simpson („Lisa“), nový Simpson („Homer“)}; Array.sort (simpsonovci); Arrays.stream (simpsons) .forEach (System.out :: println); }}
V prvom sort ()
vyvolanie, pole je zoradené podľa:
1 6 7 8 9
V druhom sort ()
vyvolanie, je zoradené podľa:
Homer Lisa
Majte na pamäti, že vlastné objekty sa musia implementovať Porovnateľné
aby bolo možné ich triediť, dokonca aj ako pole.
Môžem triediť objekty bez možnosti Porovnateľné?
Ak sa Simpsonov objekt neimplementoval Porovnateľné
, bola by vyhodená ClassCastException. Ak to spustíte ako test, uvidíte niečo ako nasledujúci výstup:
Chyba: (16, 20) java: nenašla sa žiadna vhodná metóda pre metódu sort (java.util.List) java.util.Collections.sort (java.util.List) nie je použiteľná (odvodená premenná T má nekompatibilné obmedzenia rovnosti: com.javaworld.javachallengers.sortingcomparable.Simpson spodné hranice: java.lang.Comparable) metóda java.util.Collections.sort (java.util.List, java.util.Comparator) nie je použiteľná (nemôže odvodiť typovú premennú (y) ) T (skutočné a formálne zoznamy argumentov sa líšia v dĺžke))
Tento denník môže byť mätúci, ale nemusíte sa obávať. Len majte na pamäti, že a ClassCastException
bude vyhodený pre akýkoľvek triedený objekt, ktorý neimplementuje Porovnateľné
rozhranie.
Triedenie mapy pomocou TreeMap
Rozhranie Java API obsahuje mnoho tried na pomoc s triedením, vrátane TreeMap. V príklade nižšie použijeme TreeMap
triediť kľúče do a Mapa
.
verejná trieda TreeMapExample {public static void main (String ... barney) {Map simpsonsCharacters = new TreeMap (); simpsonsCharacter.put (nový SimpsonCharacter („Moe“), „brokovnica“); simpsonsCharacter.put (nový SimpsonCharacter ("Lenny"), "Carl"); simpsonsCharacter.put (nový SimpsonCharacter („Homer“), „televízia“); simpsonsCharacter.put (nový SimpsonCharacter („Barney“), „pivo“); System.out.println (simpsonsCharacters); }}
TreeMap
používa porovnať s()
metóda implementovaná Porovnateľné
rozhranie. Každý prvok vo výslednom Mapa
je zoradený podľa kľúča. V takom prípade by bol výstup:
Barney = pivo, Homer = televízia, Lenny = Carl, Moe = brokovnica
Pamätajte však: ak sa objekt neimplementuje Porovnateľné
, a ClassCastException
bude vyhodený.
Triedenie sady pomocou TreeSet
The Nastaviť
rozhranie je zodpovedné za ukladanie jedinečných hodnôt, ale keď použijeme implementáciu TreeSet, vložené prvky sa automaticky zoradia, keď ich pridáme:
verejná trieda TreeSetExample {public static void main (String ... barney) {Set simpsonsCharacters = new TreeSet (); simpsonsCharacter.add (nový SimpsonCharacter ("Moe")); simpsonsCharacter.add (nový SimpsonCharacter ("Lenny")); simpsonsCharacter.add (nový SimpsonCharacter ("Homer")); simpsonsCharacter.add (nový SimpsonCharacter ("Barney")); System.out.println (simpsonsCharacters); }}
Výstup z tohto kódu je:
Barney, Homer, Lenny, Moe
Opäť platí, že ak použijeme objekt, ktorý nie je Porovnateľné
, a ClassCastException
bude vyhodený.
Triedenie pomocou komparátora
Čo ak by sme nechceli používať to isté porovnať s()
metóda z triedy POJO? Mohli by sme prepísať Porovnateľné
metóda na použitie inej logiky? Nižšie je uvedený príklad:
public class BadExampleOfComparable {public static void main (String ... args) {List characters = new ArrayList (); SimpsonCharacter homer = nový SimpsonCharacter ("Homer") {@Override public int compareTo (SimpsonCharacter simpson) {return this.name.length () - (simpson.name.length ()); }}; SimpsonCharacter moe = nový SimpsonCharacter ("Moe") {@Override public int compareTo (SimpsonCharacter simpson) {return this.name.length () - (simpson.name.length ()); }}; znaky.pridat (homer); znaky.pridat (moe); Zbierka.sort (znaky); System.out.println (znaky); }}
Ako vidíte, tento kód je komplikovaný a obsahuje veľa opakovaní. Museli sme prepísať porovnať s()
metóda dvakrát pre rovnakú logiku. Keby bolo viac prvkov, museli by sme replikovať logiku pre každý objekt.
Našťastie máme rozhranie komparátora, ktoré nám umožňuje odpojiť porovnať s()
logika z Java tried. Zvážte ten istý príklad prepísaný pomocou Komparátor
:
public class GoodExampleOfComparator {public static void main (String ... args) {List characters = new ArrayList (); SimpsonCharacter homer = nový SimpsonCharacter ("Homer"); SimpsonCharacter moe = nový SimpsonCharacter ("Moe"); znaky.pridat (homer); znaky.pridat (moe); Collections.sort (znaky, (komparátor. ComparingInt (znak1 -> znak1.meno.lenka ()) .thenComparingInt (znak2 -> znak2.meno.lenka ()))); System.out.println (znaky); }}
Tieto príklady demonštrujú hlavný rozdiel medzi Porovnateľné
a Komparátor
.
Použite Porovnateľné
ak pre váš objekt existuje jediné predvolené porovnanie. Použite Komparátor
keď potrebujete obísť existujúcu porovnať s()
, alebo keď potrebujete flexibilnejšie použiť konkrétnu logiku. Komparátor
odpojí logiku triedenia od vášho objektu a obsahuje porovnať s()
logika vo vašom sort ()
metóda.
Používanie komparátora s anonymnou vnútornou triedou
V tomto ďalšom príklade používame anonymnú vnútornú triedu na porovnanie hodnoty objektov. An anonymná vnútorná trieda, v tomto prípade je akákoľvek trieda, ktorá implementuje Komparátor
. Jeho použitie znamená, že nie sme povinní vytvoriť inštanciu pomenovanej triedy implementujúcej rozhranie; namiesto toho implementujeme porovnať s()
metóda vo vnútri anonymnej vnútornej triedy.
public class MarvelComparator {public static void main (String ... comparator) {List marvelHeroes = new ArrayList (); marvelHeroes.add ("SpiderMan"); marvelHeroes.add ("Wolverine"); marvelHeroes.add ("Xavier"); marvelHeroes.add ("Cyclops"); Collections.sort (marvelHeroes, new Comparator () {@Override public int compare (String hero1, String hero2) {return hero1.compareTo (hero2);}}); Collections.sort (marvelHeroes, (m1, m2) -> m1.compareTo (m2)); Collections.sort (marvelHeroes, Comparator.naturalOrder ()); marvelHeroes.forEach (System.out :: print); }}
Viac o vnútorných triedach
An anonymná vnútorná trieda je jednoducho akákoľvek trieda, na ktorej mene nezáleží, a ktorá implementuje rozhranie, ktoré deklarujeme. Takže v príklade nový Komparátor
je vlastne inštancia triedy, ktorá nemá názov, ktorá implementuje metódu s požadovanou logikou.
Používanie komparátora s výrazmi lambda
Anonymné vnútorné triedy sú podrobné, čo môže v našom kóde spôsobiť problémy. V Komparátor
rozhrania môžeme na zjednodušenie a uľahčenie čítania kódu použiť výrazy lambda. Mohli by sme to napríklad zmeniť:
Collections.sort (zázrak, nový komparátor () {@Override public int compare (reťazec hrdina1, reťazec hrdina2) {návrat hero1.compareTo (hrdina2);}});
do tohto:
Zbierky.sort (zázrak, (m1, m2) -> m1.compareTo (m2));
Menej kódu a rovnaký výsledok!
Výstup tohto kódu by bol:
Cyclops SpiderMan Wolverine Xavier
Zmenou tohto kódu by sme mohli zjednodušiť kód:
Zbierky.sort (zázrak, (m1, m2) -> m1.compareTo (m2));
do tohto:
Collections.sort (zázrak, Comparator.naturalOrder ());
Výrazy lambda v jazyku Java
Získajte viac informácií o výrazoch lambda a ďalších technikách funkčného programovania v jazyku Java.
Sú základné triedy Java porovnateľné?
Mnoho základných tried a objektov Java implementuje Porovnateľné
čo znamená, že nemusíme implementovať porovnať s()
logika pre tieto triedy. Tu je niekoľko známych príkladov:
String
verejná konečná trieda String implementuje java.io.Serializable, Comparable, CharSequence {...
Celé číslo
verejná koncová trieda Celé číslo sa rozširuje Počet implementuje porovnateľné {…
Dvojitý
verejná finálna trieda Double extends Number implements Comparable {...
Je veľa ďalších. Odporúčam vám preskúmať základné triedy Java, aby ste sa naučili ich dôležité vzorce a koncepty.
Prijmite výzvu porovnateľného rozhrania!
Vyskúšajte, čo ste sa naučili, zistením výstupu z nasledujúceho kódu. Pamätajte, že najlepšie sa naučíte, ak túto výzvu vyriešite sami tým, že si ju naštudujete. Po dosiahnutí odpovede si môžete skontrolovať odpoveď nižšie. Môžete tiež spustiť svoje vlastné testy, aby ste koncepty naplno absorbovali.
public class SortComparableChallenge {public static void main (String ... doYourBest) {Set set = new TreeSet (); set.add (nový Simpson („Homer“)); set.add (nový Simpson („Marge“)); set.add (nový Simpson („Lisa“)); set.add (nový Simpson („Bart“)); set.add (nový Simpson („Maggie“)); Zoznam zoznam = nový ArrayList (); list.addAll (sada); Zbierky.Reverzný (zoznam); list.forEach (System.out :: println); } statická trieda Simpson implementuje Comparable {Názov reťazca; public Simpson (názov reťazca) {this.name = meno; } public int compareTo (Simpson simpson) {return simpson.name.compareTo (this.name); } public String toString () {return this.name; }}}
Aký je výstup tohto kódu?
A) Bart Homer Lisa Maggie Marge B) Maggie Bart Lisa Marge Homer C) Marge Maggie Lisa Homer Bart D) Neurčité