Programerji morajo pogosto razvrstiti elemente iz baze podatkov v zbirko, matriko ali zemljevid. V Javi lahko implementiramo poljuben algoritem za razvrščanje s katero koli vrsto. Uporabljati Primerljivo
vmesnik in compareTo ()
lahko razvrstimo po abecednem vrstnem redu, Vrvica
dolžina, obratni abecedni vrstni red ali številke. The Primerjalnik
vmesnik nam omogoča, da naredimo enako, vendar na bolj prilagodljiv način.
Karkoli želimo storiti, le vedeti moramo, kako implementirati pravilno logiko razvrščanja za dani vmesnik in vrsto.
Pridobite izvorno kodo
Pridobite kodo za ta Java Challenger. Med sledenjem primerom lahko izvajate lastne teste.
Razvrščanje seznama Java s predmetom po meri
Za naš primer bomo uporabili isti POJO, ki smo ga doslej uporabljali za druge Java Challengerje. V tem prvem primeru izvedemo primerljiv vmesnik v Simpson
razred, z uporabo Simpson
v generičnem tipu:
razred Simpson izvaja Primerljivo {String name; Simpson (ime niza) {this.name = ime; } @Override public int compareTo (Simpson simpson) {return this.name.compareTo (simpson.name); }} javni razred SimpsonSorting {public static void main (String ... sortingWithList) {List simpsons = new ArrayList (); simpsons.add (novo SimpsonCharacter ("Homer")); simpsons.add (novo SimpsonCharacter ("Marge")); simpsons.add (novo SimpsonCharacter ("Bart")); simpsons.add (novo SimpsonCharacter ("Lisa")); Collections.sort (simpsoni); simpsons.stream (). map (s -> s.name) .forEach (System.out :: print); Collections.reverse (simpsoni); simpsons.stream (). forEach (System.out :: print); }}
Upoštevajte, da smo preglasili metodo compareTo () in poslali drugo Simpson
predmet. Prav tako smo preglasili toString ()
, da bi primer lažje prebrali.
The toString
metoda prikazuje vse informacije iz predmeta. Ko natisnemo predmet, bo rezultat, kar je bilo implementirano v toString ()
.
Metoda compareTo ()
The compareTo ()
metoda primerja dani predmet ali trenutni primerek z določenim predmetom, da določi vrstni red predmetov. Tukaj je hiter pogled, kako compareTo ()
dela:
Če se primerjava vrne | Potem ... |
| |
| |
| |
Uporabljamo lahko le razrede, ki so primerljivi z razvrsti ()
metoda. Če poskušamo prenesti a Simpson
ki se ne izvaja Primerljivo
, bomo prejeli napako pri sestavljanju.
The razvrsti ()
metoda uporablja polimorfizem s prenašanjem katerega koli predmeta, ki je Primerljivo
. Predmeti bodo nato razvrščeni po pričakovanjih.
Rezultat prejšnje kode bi bil:
Bart Homer Lisa Marge
Če bi želeli obrniti vrstni red, bi ga lahko zamenjali razvrsti ()
za vzvratno ()
; od:
Collections.sort (simpsoni);
do:
Collections.reverse (simpsoni);
Uvajanje vzvratno ()
metoda bi prejšnji izhod spremenila v:
Marge Lisa Homer Bart
Razvrščanje polja Java
V Javi lahko vrsto razvrstimo s poljubno vrsto, če le ta izvaja Primerljivo
vmesnik. Tu je primer:
javni razred ArraySorting {javna statična 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 = new Simpson [] {new Simpson ("Lisa"), new Simpson ("Homer")}; Arrays.sort (simpsoni); Arrays.stream (simpsons) .forEach (System.out :: println); }}
V prvem razvrsti ()
priklic, je matrika razvrščena na:
1 6 7 8 9
V drugem razvrsti ()
klic, se razvrsti na:
Homer Lisa
Upoštevajte, da morajo biti predmeti po meri implementirani Primerljivo
za razvrščanje, tudi kot matriko.
Ali lahko razvrstim predmete brez primerljivega?
Če se Simpsonov predmet ni izvajal Primerljivo
, vržen bi bil ClassCastException. Če zaženete to kot preizkus, boste videli nekaj takega:
Napaka: (16, 20) java: za metodo razvrščanja (java.util.List) ni najdena ustrezna metoda java.util.Collections.sort (java.util.List) ni uporabna (sklepna spremenljivka T ima nezdružljive omejitve glede enakosti: com.javaworld.javachallengers.sortingcomparable.Simpson spodnje meje: java.lang.Comparable) metoda java.util.Collections.sort (java.util.List, java.util.Comparator) ni uporabna (ni mogoče določiti spremenljivk tipa (s) ) T (dejanski in formalni seznami argumentov se razlikujejo po dolžini))
Ta dnevnik je morda zmeden, vendar ne skrbite. Ne pozabite, da a ClassCastException
bo vržen za vsak razvrščen predmet, ki ne izvaja datoteke Primerljivo
vmesnik.
Razvrščanje zemljevida z TreeMapom
Java API vključuje številne razrede za pomoč pri razvrščanju, vključno z TreeMap. V spodnjem primeru uporabljamo TreeMap
za razvrščanje tipk v Zemljevid
.
javni razred TreeMapExample {public static void main (String ... barney) {Map simpsonsCharacters = new TreeMap (); simpsonsCharacters.put (novo SimpsonCharacter ("Moe"), "puška"); simpsonsCharacters.put (novo SimpsonCharacter ("Lenny"), "Carl"); simpsonsCharacters.put (novo SimpsonCharacter ("Homer"), "televizija"); simpsonsCharacters.put (novo SimpsonCharacter ("Barney"), "pivo"); System.out.println (simpsonsCharacters); }}
TreeMap
uporablja compareTo ()
metoda, ki jo izvaja Primerljivo
vmesnik. Vsak element v nastalem Zemljevid
je razvrščeno po ključu. V tem primeru bi bil rezultat:
Barney = pivo, Homer = televizija, Lenny = Carl, Moe = puška
Vendar ne pozabite: če se objekt ne izvede Primerljivo
, a ClassCastException
bo vržen.
Razvrščanje niza z TreeSet
The Nastavite
vmesnik je odgovoren za shranjevanje edinstvenih vrednosti, toda ko uporabimo izvedbo TreeSet, bodo vstavljeni elementi samodejno razvrščeni, ko jih dodamo:
javni razred TreeSetExample {public static void main (String ... barney) {Set simpsonsCharacters = new TreeSet (); simpsonsCharacters.add (novo SimpsonCharacter ("Moe")); simpsonsCharacters.add (novo SimpsonCharacter ("Lenny")); simpsonsCharacters.add (novo SimpsonCharacter ("Homer")); simpsonsCharacters.add (novo SimpsonCharacter ("Barney")); System.out.println (simpsonsCharacters); }}
Rezultat te kode je:
Barney, Homer, Lenny, Moe
Še enkrat, če uporabimo objekt, ki ni Primerljivo
, a ClassCastException
bo vržen.
Razvrščanje s primerjalnikom
Kaj pa če ne bi želeli uporabiti istega compareTo ()
metoda iz razreda POJO? Lahko preglasimo Primerljivo
metoda za uporabo drugačne logike? Spodaj je primer:
javni razred BadExampleOfComparable {javna statična void main (String ... args) {Znaki na seznamu = new ArrayList (); SimpsonCharacter homer = novo SimpsonCharacter ("Homer") {@ Preveri javni int compareTo (SimpsonCharacter simpson) {return this.name.length () - (simpson.name.length ()); }}; SimpsonCharacter moe = novo SimpsonCharacter ("Moe") {@ Preveri javni int compareTo (SimpsonCharacter simpson) {return this.name.length () - (simpson.name.length ()); }}; znaki.add (homer); characters.add (moe); Collections.sort (znaki); System.out.println (znaki); }}
Kot lahko vidite, je ta koda zapletena in vključuje veliko ponovitev. Morali smo preglasiti compareTo ()
dvakrat za isto logiko. Če bi bilo elementov več, bi morali ponoviti logiko za vsak predmet.
Na srečo imamo primerjalni vmesnik, ki nam omogoča, da ločimo compareTo ()
logika iz razredov Java. Razmislite o istem zgornjem primeru, ki ste ga znova napisali z uporabo Primerjalnik
:
javni razred GoodExampleOfComparator {public static void main (String ... args) {Znaki seznama = new ArrayList (); SimpsonCharacter homer = nov SimpsonCharacter ("Homer"); SimpsonCharacter moe = novo SimpsonCharacter ("Moe"); znaki.add (homer); characters.add (moe); Collections.sort (znaki, (Primerjalnik. ComparingInt (character1 -> character1.name.length ()). ThenComparingInt (character2 -> character2.name.length ()))); System.out.println (znaki); }}
Ti primeri kažejo glavno razliko med Primerljivo
in Primerjalnik
.
Uporaba Primerljivo
ko obstaja ena, privzeta primerjava za vaš predmet. Uporaba Primerjalnik
ko morate zaobiti obstoječega compareTo ()
ali kadar morate uporabiti določeno logiko na bolj prilagodljiv način. Primerjalnik
loči logiko razvrščanja od vašega predmeta in vsebuje compareTo ()
logiko znotraj vašega razvrsti ()
metoda.
Uporaba primerjalnika z anonimnim notranjim razredom
V naslednjem primeru za primerjavo vrednosti predmetov uporabljamo anonimni notranji razred. An anonimni notranji razred, v tem primeru je kateri koli razred, ki izvaja Primerjalnik
. Z njegovo uporabo pomeni, da nismo vezani na instanciranje imenovanega razreda, ki izvaja vmesnik; namesto tega izvajamo compareTo ()
metoda znotraj anonimnega notranjega razreda.
javni razred MarvelComparator {public static void main (String ... comparator) {Seznam marvelHeroes = new ArrayList (); marvelHeroes.add ("SpiderMan"); marvelHeroes.add ("Wolverine"); marvelHeroes.add ("Xavier"); marvelHeroes.add ("Kiklop"); Collections.sort (marvelHeroes, new Comparator () {@Preveri javno int primerjavo (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); }}
Več o notranjih tečajih
An anonimni notranji razred je preprosto vsak razred, katerega ime ni pomembno in ki izvaja vmesnik, ki ga prijavljamo. Torej v primeru novo Primerjalnik
je dejansko instancija razreda, ki nima imena, ki metodo izvaja z logiko, ki jo želimo.
Uporaba primerjalnika z lambda izrazi
Anonimni notranji razredi so podrobni, kar lahko povzroči težave v naši kodi. V Primerjalnik
vmesnika lahko z lambda izrazi poenostavimo in olajšamo branje kode. Lahko bi na primer to spremenili:
Collections.sort (marvel, new Comparator () {@Preveri javno int primerjavo (String hero1, String hero2) {return hero1.compareTo (hero2);}});
za to:
Collections.sort (marvel, (m1, m2) -> m1.compareTo (m2));
Manj kode in enak rezultat!
Rezultat te kode bi bil:
Kiklop SpiderMan Wolverine Xavier
Kodo bi lahko poenostavili s spremembo tega:
Collections.sort (marvel, (m1, m2) -> m1.compareTo (m2));
za to:
Collections.sort (marvel, Comparator.naturalOrder ());
Lambda izrazi v Javi
Preberite več o lambda izrazih in drugih tehnikah funkcionalnega programiranja v Javi.
So osnovni razredi Java primerljivi?
Številni osnovni razredi in predmeti Java izvajajo Primerljivo
vmesnik, kar pomeni, da nam ni treba izvajati compareTo ()
logika za te razrede. Tu je nekaj znanih primerov:
Vrvica
javni končni razred String implementira java.io.Serializable, Comparable, CharSequence {...
Celo število
javni končni razred Integer razširja Število izvedb Primerljivo {…
Dvojno
javni končni razred Double extends Število izvedb Primerljivo {...
Obstaja veliko drugih. Priporočam vam, da raziščete osnovne razrede Java, da se naučite njihovih pomembnih vzorcev in konceptov.
Sprejmite izziv primerljivega vmesnika!
Preizkusite, kaj ste se naučili, tako da ugotovite, kakšen je rezultat naslednje kode. Ne pozabite, da se boste najbolje naučili, če boste ta izziv rešili sami, samo če ga boste preučili. Ko ste dobili odgovor, ga lahko preverite spodaj. Izvedete lahko tudi lastne teste, da v celoti prevzamete koncepte.
javni razred 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")); Seznam seznamov = new ArrayList (); list.addAll (set); Collections.reverse (seznam); list.forEach (System.out :: println); } statični razred Simpson izvaja Primerljivo {String name; javni Simpson (ime niza) {this.name = ime; } public int compareTo (Simpson simpson) {return simpson.name.compareTo (this.name); } javni String toString () {return this.name; }}}
Kateri je rezultat te kode?
A) Bart Homer Lisa Maggie Marge B) Maggie Bart Lisa Marge Homer C) Marge Maggie Lisa Homer Bart D) Nedoločeno