Ohjelmoijien on usein lajiteltava elementit tietokannasta kokoelmaan, taulukkoihin tai karttoihin. Java: ssa voimme toteuttaa minkä tahansa haluamamme lajittelualgoritmin mihin tahansa tyyppiin. Käyttämällä Vertailukelpoinen
käyttöliittymä ja vertaa()
menetelmällä voimme lajitella aakkosjärjestyksessä, Merkkijono
pituus, käänteinen aakkosjärjestys tai numerot. Vertailija
käyttöliittymän avulla voimme tehdä saman, mutta joustavammin.
Mitä haluamme tehdä, meidän on vain tiedettävä, kuinka toteuttaa oikea lajittelulogiikka annetulle käyttöliittymälle ja tyypille.
Hanki lähdekoodi
Hanki koodi tälle Java Challengerille. Voit suorittaa omia testejä samalla kun noudatat esimerkkejä.
Java-luettelon lajittelu mukautetulla objektilla
Esimerkissä käytämme samaa POJO: ta, jota olemme tähän mennessä käyttäneet muille Java-haastajille. Tässä ensimmäisessä esimerkissä toteutamme Vertailukelpoisen käyttöliittymän Simpson
luokassa käyttäen Simpson
yleisessä tyypissä:
luokan Simpson toteuttaa Vertailukelpoinen {String name; Simpson (merkkijono) {this.name = nimi; } @Override public int CompareTo (Simpson simpson) {palauta this.name.compareTo (simpson.name); }} public class SimpsonSorting {public static void main (String ... sortingWithList) {Lista simpsonit = uusi ArrayList (); simpsons.add (uusi SimpsonCharacter ("Homer")); simpsons.add (uusi SimpsonCharacter ("Marge")); simpsons.add (uusi SimpsonCharacter ("Bart")); simpsons.add (uusi SimpsonCharacter ("Lisa")); Collections. Lajittelu (simpsonit); simpsons.stream (). map (s -> s.name) .forEach (System.out :: print); Kokoelmat.käänteinen (simpsonit); simpsons.stream (). forEach (System.out :: print); }}
Huomaa, että olemme ohittaneet CompareTo () -menetelmän ja siirtäneet toisen Simpson
esine. Olemme myös ohittaneet toString ()
menetelmällä, vain jotta esimerkki olisi helpompi lukea.
merkkijono
menetelmä näyttää kaikki objektin tiedot. Kun tulostamme objektin, tulosteet ovat mitä tahansa toString ()
.
CompareTo () -menetelmä
vertaa()
menetelmä vertaa tiettyä objektia tai nykyistä esiintymää määritettyyn objektiin objektien järjestyksen määrittämiseksi. Tässä on nopea kuvaus miten vertaa()
toimii:
Jos vertailu palaa | Sitten ... |
| |
| |
| |
Voimme käyttää vain luokkia, jotka ovat verrattavissa järjestellä()
menetelmä. Jos yritämme läpäistä a Simpson
jota ei toteuteta Vertailukelpoinen
, saamme kokoamisvirheen.
järjestellä()
menetelmä käyttää polymorfismia ohittamalla minkä tahansa objektin, joka on Vertailukelpoinen
. Objektit lajitellaan sitten odotetulla tavalla.
Edellisen koodin lähtö olisi:
Bart Homer Lisa Marge
Jos haluaisimme muuttaa järjestystä, voisimme vaihtaa järjestellä()
a käänteinen()
; alkaen:
Collections. Lajittelu (simpsonit);
vastaanottajalle:
Kokoelmat.käänteinen (simpsonit);
Käyttöönotto käänteinen()
menetelmä muuttaisi edellisen tuotoksen muotoon:
Marge Lisa Homer Bart
Java-taulukon lajittelu
Java: ssa voimme lajitella taulukon haluamallamme tavalla, kunhan se toteuttaa Vertailukelpoinen
käyttöliittymä. Tässä on esimerkki:
public class ArraySorting {public static void main (String ... moeTavern) {int [] moesPints = new int [] {9, 8, 7, 6, 1}; Taulukot.lajittelu (moesPints); Taulukot.stream (moesPints) .forEach (System.out :: print); Simpson [] simpsons = uusi Simpson [] {uusi Simpson ("Lisa"), uusi Simpson ("Homer")}; Taulukot.lajittelu (simpsonit); Arrays.stream (simpsons) .forEach (System.out :: println); }}
Ensimmäisessä järjestellä()
kutsu, taulukko on lajiteltu:
1 6 7 8 9
Toisessa järjestellä()
kutsu, se on lajiteltu:
Homer Lisa
Muista, että mukautettujen objektien on toteutettava Vertailukelpoinen
lajiteltavaksi, jopa matriisina.
Voinko lajitella objekteja ilman vertailukelpoista?
Jos Simpson-objektia ei toteutettu Vertailukelpoinen
, ClassCastException heitetään. Jos suoritat tämän testinä, näet jotain seuraavanlaista:
Virhe: (16, 20) java: Lajittelu- (java.util.List) -menetelmälle ei löytynyt sopivaa menetelmää com.javaworld.javachallengers.sortingcomparable. ) T (todelliset ja muodolliset argumenttiluettelot eroavat toisistaan)
Tämä loki voi olla hämmentävä, mutta älä huoli. Pidä vain mielessä, että a ClassCastException
heitetään jokaiselle lajitellulle objektille, joka ei toteuta Vertailukelpoinen
käyttöliittymä.
Kartan lajittelu TreeMapilla
Java-sovellusliittymä sisältää monia luokkia, jotka auttavat lajittelussa, mukaan lukien TreeMap. Seuraavassa esimerkissä käytämme PuuKartta
lajitella avaimet a Kartta
.
public class TreeMapExample {public static void main (String ... barney) {Map simpsonsCharacters = new TreeMap (); simpsonsCharacters.put (uusi SimpsonCharacter ("Moe"), "haulikko"); simpsonsCharacters.put (uusi SimpsonCharacter ("Lenny"), "Carl"); simpsonsCharacters.put (uusi SimpsonCharacter ("Homer"), "televisio"); simpsonsCharacters.put (uusi SimpsonCharacter ("Barney"), "olut"); System.out.println (simpsonsCharacters); }}
PuuKartta
käyttää vertaa()
- menetelmä, jonka Vertailukelpoinen
käyttöliittymä. Jokainen tuloksena olevan elementin Kartta
on lajiteltu avaimensa mukaan. Tässä tapauksessa tuotos olisi:
Barney = olut, Homer = televisio, Lenny = Carl, Moe = haulikko
Muista kuitenkin: jos objekti ei toteudu Vertailukelpoinen
, a ClassCastException
heitetään.
Sarjan lajittelu TreeSetin avulla
Aseta
käyttöliittymä on vastuussa yksilöllisten arvojen tallentamisesta, mutta kun käytämme TreeSet-toteutusta, lisätyt elementit lajitellaan automaattisesti, kun ne lisätään:
public class TreeSetExample {public static void main (String ... barney) {Set simpsonsCharacters = new TreeSet (); simpsonsCharacters.add (uusi SimpsonCharacter ("Moe")); simpsonsCharacters.add (uusi SimpsonCharacter ("Lenny")); simpsonsCharacters.add (uusi SimpsonCharacter ("Homer")); simpsonsCharacters.add (uusi SimpsonCharacter ("Barney")); System.out.println (simpsonsCharacters); }}
Tämän koodin lähtö on:
Barney, Homer, Lenny, Moe
Jälleen, jos käytämme kohdetta, joka ei ole Vertailukelpoinen
, a ClassCastException
heitetään.
Lajittelu vertailijan kanssa
Entä jos emme halua käyttää samaa vertaa()
menetelmä POJO-luokasta? Voisimmeko ohittaa Vertailukelpoinen
menetelmä käyttää erilaista logiikkaa? Alla on esimerkki:
public class BadExampleOfComparable {public static void main (String ... args) {Luettelomerkit = uusi ArrayList (); SimpsonCharacter homer = uusi SimpsonCharacter ("Homer") {@Override public int CompareTo (SimpsonCharacter simpson) {return this.name.length () - (simpson.name.length ()); }}; SimpsonCharacter moe = uusi SimpsonCharacter ("Moe") {@Override public int CompareTo (SimpsonCharacter simpson) {return this.name.length () - (simpson.name.length ()); }}; merkit. add (homer); merkit. lisää (moe); Collections. Lajittelu (merkit); System.out.println (merkkiä); }}
Kuten näette, tämä koodi on monimutkainen ja sisältää paljon toistoja. Meidän piti ohittaa vertaa()
kahdesti samaa logiikkaa varten. Jos elementtejä olisi enemmän, meidän olisi toistettava jokaisen objektin logiikka.
Onneksi meillä on Comparator-käyttöliittymä, jonka avulla voimme irrottaa vertaa()
logiikka Java-luokista. Harkitse samaa esimerkkiä, joka on kirjoitettu uudestaan Vertailija
:
public class GoodExampleOfComparator {public static void main (String ... args) {Luettelomerkit = uusi ArrayList (); SimpsonCharacter homer = uusi SimpsonCharacter ("Homer"); SimpsonCharacter moe = uusi SimpsonCharacter ("Moe"); merkit. add (homer); merkit. lisää (moe); Collections.sort (merkit, (Comparator. VertaaInt (merkki1 -> merkki1.nimi.pituus ()) .thenComparingInt (merkki2 -> merkki2.nimi.pituus ()))); System.out.println (merkkiä); }}
Nämä esimerkit osoittavat tärkeimmän eron Vertailukelpoinen
ja Vertailija
.
Käyttää Vertailukelpoinen
kun kohteellesi on yksi, oletusarvoinen vertailu. Käyttää Vertailija
kun sinun täytyy kiertää olemassa olevaa vertaa()
tai kun sinun on käytettävä tiettyä logiikkaa joustavammin. Vertailija
irrottaa lajittelulogiikan objektistasi ja sisältää vertaa()
logiikka sisällä järjestellä()
menetelmä.
Comparatorin käyttö nimettömän sisäisen luokan kanssa
Tässä seuraavassa esimerkissä vertaamme esineiden arvoa nimettömän sisäisen luokan kanssa. An tuntematon sisempi luokka, tässä tapauksessa on mikä tahansa luokka, joka toteuttaa Vertailija
. Sen käyttö tarkoittaa, että emme ole sitoutuneita nimeämään luokkaa ilmentämään käyttöliittymää; sen sijaan toteutamme vertaa()
menetelmä tuntemattoman sisäisen luokan sisällä.
public class MarvelComparator {public static void main (String ... Comparator) {Lista marvelHeroes = new ArrayList (); marvelHeroes.add ("Hämähäkkimies"); marvelHeroes.add ("Ahma"); marvelHeroes.add ("Xavier"); marvelHeroes.add ("Kyklooppi"); Collections.sort (marvelHeroes, new Comparator () {@Override public int vertaile (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); }}
Lisätietoja sisemmistä luokista
An tuntematon sisempi luokka on yksinkertaisesti mikä tahansa luokka, jonka nimellä ei ole väliä ja joka toteuttaa ilmoitettavan käyttöliittymän. Joten esimerkissä uusi Vertailija
on itse asiassa luokan luokse, jolla ei ole nimeä, mikä toteuttaa menetelmän haluamallamme logiikalla.
Comparatorin käyttö lambda-lausekkeiden kanssa
Anonyymit sisäiset luokat ovat yksityiskohtaisia, mikä voi aiheuttaa ongelmia koodissamme. vuonna Vertailija
käyttöliittymän avulla voimme käyttää lambda-lausekkeita yksinkertaistamaan ja helpottamaan koodin lukemista. Voisimme esimerkiksi muuttaa tätä:
Collections.sort (ihme, uusi Comparator () {@Override public int vertaile (String hero1, String hero2) {return hero1.compareTo (hero2);}});
tähän:
Kokoelmat. Lajittelu (ihme, (m1, m2) -> m1.vertaTo (m2));
Vähemmän koodia ja sama tulos!
Tämän koodin lähtö olisi:
Kyklooppi SpiderMan Wolverine Xavier
Voimme tehdä koodista vielä yksinkertaisemman muuttamalla tätä:
Kokoelmat. Lajittelu (ihme, (m1, m2) -> m1.vertaTo (m2));
tähän:
Collections.sort (ihme, Comparator.naturalOrder ());
Lambda-lausekkeet Java-kielellä
Lue lisää lambda-lausekkeista ja muista Java-toiminnallisista ohjelmointitekniikoista.
Ovatko ydin Java-luokat vertailukelpoisia?
Monet Java-ydinluokat ja -objektit toteuttavat Vertailukelpoinen
käyttöliittymä, mikä tarkoittaa, että meidän ei tarvitse ottaa käyttöön vertaa()
näiden luokkien logiikka. Tässä on muutama tuttu esimerkki:
Merkkijono
public final class String toteuttaa java.io.Serializable, Comparable, CharSequence {...
Kokonaisluku
julkinen loppuluokka Kokonaisluku laajentaa Numerototeutuksia Vertailukelpoinen {…
Kaksinkertainen
julkinen finaaliluokka Tuplalaajennukset Numerotarvikkeet Vertailukelpoinen {...
On monia muita. Kehotan teitä tutkimaan Java-ydinluokkia oppimaan niiden tärkeät mallit ja käsitteet.
Vastaa Vertailukelpoisen käyttöliittymän haasteeseen!
Testaa oppimasi selvittämällä seuraavan koodin lähtö. Muista, että opit parhaiten, jos ratkaiset tämän haasteen itse vain tutkimalla sitä. Kun olet saanut vastauksen, voit tarkistaa vastauksen alla. Voit myös suorittaa omat testisi käsitteiden täydelliseksi hyödyntämiseksi.
public class SortComparableChallenge {public static void main (String ... doYourBest) {Set set = new TreeSet (); set.add (uusi Simpson ("Homer")); set.add (uusi Simpson ("Marge")); set.add (uusi Simpson ("Lisa")); set.add (uusi Simpson ("Bart")); set.add (uusi Simpson ("Maggie")); List list = new ArrayList (); list.addAll (sarja); Kokoelmat.käänteinen (luettelo); list.forEach (System.out :: println); } staattinen luokka Simpson toteuttaa Vertailukelpoinen {String name; julkinen Simpson (merkkijono) {this.name = nimi; } public int vertaileTo (Simpson simpson) {palauta simpson.nimi.vertaaTo (tämä.nimi); } public String toString () {palauta tämä.nimi; }}}
Mikä on tämän koodin lähtö?
A) Bart Homer Lisa Maggie Marge B) Maggie Bart Lisa Marge Homer C) Marge Maggie Lisa Homer Bart D) Määrittelemätön