Programmēšana

Kārtošana ar Java un Comparable

Programmētājiem bieži ir jāsakārto elementi no datu bāzes kolekcijā, masīvā vai kartē. Java valodā mēs varam ieviest jebkuru vēlamo šķirošanas algoritmu ar jebkuru tipu. Izmantojot Salīdzināms interfeiss un Salīdzinot ar() metodi, mēs varam kārtot, izmantojot alfabētisko secību, Stīga garums, apgrieztā alfabētiskā secība vai skaitļi. The Salīdzinātājs interfeiss ļauj mums darīt to pašu, bet elastīgāk.

Lai ko mēs vēlētos darīt, mums vienkārši jāzina, kā ieviest pareizo šķirošanas loģiku dotajam interfeisam un tipam.

Iegūstiet pirmkodu

Iegūstiet šī Java Challenger kodu. Kamēr sekojat piemēriem, varat pats veikt testus.

Java saraksta šķirošana ar pielāgotu objektu

Šajā piemērā mēs izmantosim to pašu POJO, ko līdz šim izmantojām citiem Java izaicinātājiem. Šajā pirmajā piemērā mēs ieviešam salīdzināmo saskarni Simpsons klase, izmantojot Simpsons vispārējā veidā:

 klases Simpsons ievieš Salīdzināms {String name; Simpsons (virknes nosaukums) {this.name = name; } @Orride public int salīdzinātTo (Simpson simpson) {return this.name.compareTo (simpson.name); }} public class SimpsonSorting {public static void main (String ... sortingWithList) {Saraksts simpsons = new ArrayList (); simpsons.add (jauns SimpsonCharacter ("Homer")); simpsons.add (jauns SimpsonCharacter ("Marge")); simpsons.add (jauns SimpsonCharacter ("Bart")); simpsons.add (jauns SimpsonCharacter ("Lisa")); Kolekcijas.kārtot (simpsoni); simpsons.stream (). karte (s -> s.name). katram (System.out :: print); Kolekcijas.reverss (simpsoni); simpsons.stream (). forEach (System.out :: print); }} 

Ņemiet vērā, ka esam ignorējuši metodi salīdzināt () un nodevuši citu Simpsons objekts. Mēs arī esam ignorējuši toString () metodi, lai piemēru būtu vieglāk lasīt.

The toString metode parāda visu objekta informāciju. Kad mēs izdrukāsim objektu, izeja būs tāda, kāda tika ieviesta toString ().

Metode salīdzināt ()

The Salīdzinot ar() metode salīdzina konkrēto objektu vai pašreizējo gadījumu ar noteiktu objektu, lai noteiktu objektu secību. Šeit ir īss ieskats kā Salīdzinot ar() darbojas:

Ja salīdzinājums atgriežas

Tad ...

  >= 1

  this.name> simpson.name

  0

  this.name == simpson.name

  <= -1

  this.name <simpson.name

Mēs varam izmantot tikai klases, kas ir salīdzināmas ar kārtot () metodi. Ja mēs mēģinām iziet a Simpsons kas netiek īstenots Salīdzināms, mēs saņemsim sastādīšanas kļūdu.

The kārtot () metode izmanto polimorfismu, nododot jebkuru objektu, kas ir Salīdzināms. Pēc tam objekti tiks kārtoti, kā paredzēts.

Iepriekšējā koda izeja būtu:

 Barts Homērs Liza Mārdža 

Ja mēs vēlētos mainīt secību, mēs varētu apmainīt kārtot () priekš reverss (); no:

 Kolekcijas.kārtot (simpsoni); 

uz:

 Kolekcijas.reverss (simpsoni); 

Izvietošana reverss () metode mainītu iepriekšējo izvadi uz:

 Mārdža Liza Homēra Bārta 

Java masīva kārtošana

Java valodā mēs varam kārtot masīvu ar jebkuru vēlamo tipu, ja vien tas ievieš Salīdzināms interfeiss. Lūk, piemērs:

 public class ArraySorting {public static void main (String ... moeTavern) {int [] moesPints ​​= new int [] {9, 8, 7, 6, 1}; Masīvi.kārtot (moesPints); Masīvi.stream (moesPints) .forEach (System.out :: print); Simpsons [] simpsons = jauns Simpsons [] {jauns Simpsons ("Lisa"), jauns Simpsons ("Homērs")}; Masīvi.sortēt (simpsoni); Masīvi.stream (simpsons) .forEach (System.out :: println); }} 

Pirmajā kārtot () izsaukums, masīvs tiek sakārtots šādi:

 1 6 7 8 9 

Otrajā kārtot () izsaukums, tas tiek sakārtots šādi:

 Homērs Liza 

Paturiet prātā, ka pielāgotie objekti ir jāievieš Salīdzināms lai tos varētu kārtot pat kā masīvu.

Vai es varu kārtot objektus bez Salīdzināms?

Ja Simpson objekts netika ieviests Salīdzināms, tiks izmests ClassCastException. Ja palaidīsit to kā testu, redzēsit šādu izvadi:

 Kļūda: (16, 20) java: nav atrasta piemērota metode, lai kārtotu (java.util.List) metodi java.util.Collections.sort (java.util.List) nav piemērojama (secinājuma mainīgajam T ir nesaderīgi ierobežojumi attiecībā uz vienlīdzības ierobežojumiem: com.javaworld.javachallengers.sortingcomparable.Simpson zemākās robežas: java.lang.Comparable) metode java.util.Collections.sort (java.util.List, java.util.Comparator) nav piemērojama (nevar secināt, ka mainīgais (s) ) T (faktisko un formālo argumentu saraksti atšķiras pēc garuma)) 

Šis žurnāls var būt mulsinošs, taču neuztraucieties. Vienkārši paturiet prātā, ka a ClassCastException tiks izmests par jebkuru sakārtotu objektu, kas neievieš Salīdzināms interfeiss.

Kartes kārtošana ar TreeMap

Java API ietver daudzas klases, kas palīdz šķirot, ieskaitot TreeMap. Tālāk sniegtajā piemērā mēs izmantojam TreeMap kārtot atslēgas a Karte.

 public class TreeMapExample {public static void main (String ... barney) {Map simpsonsCharacters = new TreeMap (); simpsonsCharacters.put (jauns SimpsonCharacter ("Moe"), "bise"); simpsonsCharacters.put (jauns SimpsonCharacter ("Lenny"), "Carl"); simpsonsCharacters.put (jauns SimpsonCharacter ("Homer"), "televīzija"); simpsonsCharacters.put (jauns SimpsonCharacter ("Barney"), "alus"); System.out.println (simpsonsCharacters); }} 

TreeMap izmanto Salīdzinot ar() metode, ko ieviesusi Salīdzināms interfeiss. Katrs iegūtais elements Karte tiek sakārtots pēc atslēgas. Šajā gadījumā produkcija būtu:

 Bārnijs = alus, Homērs = televīzija, Lenijs = Karls, Moe = bise 

Tomēr atcerieties: ja objekts netiek ieviests Salīdzināms, a ClassCastException tiks izmests.

Komplekta šķirošana ar TreeSet

The Iestatiet interfeiss ir atbildīgs par unikālu vērtību glabāšanu, bet, kad izmantosim TreeSet ieviešanu, ievietotie elementi tiks automātiski sakārtoti, kad tos pievienosim:

 public class TreeSetExample {public static void main (String ... barney) {Set simpsonsCharacters = new TreeSet (); simpsonsCharacters.add (jauns SimpsonCharacter ("Moe")); simpsonsCharacters.add (jauns SimpsonCharacter ("Lenny")); simpsonsCharacters.add (jauns SimpsonCharacter ("Homer")); simpsonsCharacters.add (jauns SimpsonCharacter ("Barney")); System.out.println (simpsonsCharacters); }} 

Šī koda izeja ir:

 Bārnijs, Homērs, Lenijs, Moe 

Atkal, ja mēs izmantojam objektu, kas nav Salīdzināms, a ClassCastException tiks izmests.

Šķirošana ar Comparator

Ko darīt, ja mēs nevēlētos izmantot to pašu Salīdzinot ar() metode no POJO klases? Vai mēs varētu ignorēt Salīdzināms metodi, lai izmantotu citu loģiku? Zemāk ir sniegts piemērs:

 public class BadExampleOfComparable {public static void main (String ... args) {Saraksta rakstzīmes = new ArrayList (); SimpsonCharacter homer = new SimpsonCharacter ("Homer") {@Override public int salīdzinātTo (SimpsonCharacter simpson) {return this.name.length () - (simpson.name.length ()); }}; SimpsonCharacter moe = new SimpsonCharacter ("Moe") {@Override public int salīdzinātTo (SimpsonCharacter simpson) {return this.name.length () - (simpson.name.length ()); }}; rakstzīmes.add (homers); rakstzīmes.pievienot (moe); Kolekcijas.kārtot (rakstzīmes); System.out.println (rakstzīmes); }} 

Kā redzat, šis kods ir sarežģīts un ietver daudz atkārtojumu. Mums nācās ignorēt Salīdzinot ar() metodi divreiz vienai un tai pašai loģikai. Ja būtu vairāk elementu, mums būtu jāatkārto loģika katram objektam.

Par laimi mums ir Comparator saskarne, kas ļauj mums atvienot Salīdzinot ar() loģika no Java klasēm. Apsveriet to pašu iepriekš minēto piemēru, kas pārrakstīts, izmantojot Salīdzinātājs:

 public class GoodExampleOfComparator {public static void main (String ... args) {Saraksta rakstzīmes = new ArrayList (); SimpsonCharacter homer = jauns SimpsonCharacter ("Homer"); SimpsonCharacter moe = jauns SimpsonCharacter ("Moe"); rakstzīmes.add (homers); rakstzīmes.pievienot (moe); Collections.sort (rakstzīmes, (Comparator. ComparInt (raksturs1 -> rakstzīme1.nosaukums.length ()) .thenComparingInt (raksturs2 -> rakstzīme2.nosaukums.length ()))); System.out.println (rakstzīmes); }} 

Šie piemēri parāda galveno atšķirību starp Salīdzināms un Salīdzinātājs.

Izmantot Salīdzināms kad jūsu objektam ir viens noklusējuma salīdzinājums. Izmantot Salīdzinātājskad jums ir nepieciešams apiet esošo Salīdzinot ar()vai kad jums ir jāizmanto īpaša loģika elastīgāk. Salīdzinātājs atdala šķirošanas loģiku no objekta un satur Salīdzinot ar() loģika jūsu kārtot () metodi.

Comparator izmantošana ar anonīmu iekšējo klasi

Šajā nākamajā piemērā mēs izmantojam anonīmu iekšējo klasi, lai salīdzinātu objektu vērtību. An anonīma iekšējā klase, šajā gadījumā ir jebkura klase, kas īsteno Salīdzinātājs. Tā lietošana nozīmē, ka mums nav pienākuma saīsināt nosaukto klasi, kas ievieš saskarni; tā vietā mēs ieviešam Salīdzinot ar() metode anonīmās iekšējās klases iekšienē.

 publiskā klase MarvelComparator {public static void main (String ... Comparator) {Saraksts marvelHeroes = new ArrayList (); marvelHeroes.add ("Zirnekļcilvēks"); marvelHeroes.add ("Wolverine"); marvelHeroes.add ("Ksavjers"); marvelHeroes.add ("Cyclops"); Collections.sort (marvelHeroes, new Comparator () {@ Pārvarēt public int salīdzināt (String hero1, String hero2) {return hero1.compareTo (hero2);}}); Kolekcijas.kārtot (marvelHeroes, (m1, m2) -> m1.compareTo (m2)); Collections.sort (marvelHeroes, Comparator.naturalOrder ()); marvelHeroes.forEach (System.out :: print); }} 

Vairāk par iekšējām klasēm

An anonīma iekšējā klase ir vienkārši jebkura klase, kuras nosaukumam nav nozīmes un kura īsteno mūsu deklarēto saskarni. Tātad piemērā jaunais Salīdzinātājs faktiski ir klases, kurai nav nosaukuma, piemērs, kas metodi ievieš ar vēlamo loģiku.

Izmantojot Comparator ar lambda izteiksmēm

Anonīmas iekšējās klases ir izteiksmīgas, kas var radīt problēmas mūsu kodā. Iekš Salīdzinātājs interfeisu, mēs varam izmantot lambda izteicienus, lai vienkāršotu un atvieglotu koda lasīšanu. Piemēram, mēs to varētu mainīt:

 Collections.sort (brīnums, jauns Comparator () {@ Pārvarēt public int salīdzināt (String hero1, String hero2) {return hero1.compareTo (hero2);}}); 

uz šo:

 Kolekcijas.kārtot (brīnums, (m1, m2) -> m1.compareTo (m2)); 

Mazāk koda un tas pats rezultāts!

Šī koda izeja būtu:

 Cyclops SpiderMan Wolverine Xavier 

Mēs varētu padarīt kodu vēl vienkāršāku, mainot šo:

 Kolekcijas.kārtot (brīnums, (m1, m2) -> m1.compareTo (m2)); 

uz šo:

 Collections.sort (brīnums, Comparator.naturalOrder ()); 

Lambda izteicieni Java valodā

Uzziniet vairāk par lambda izteiksmēm un citām Java funkcionālajām programmēšanas metodēm.

Vai Java pamatklases ir salīdzināmas?

Daudzi Java pamatklases un objekti ievieš Salīdzināms interfeiss, kas nozīmē, ka mums nav jāievieš Salīdzinot ar() loģika šīm klasēm. Šeit ir daži pazīstami piemēri:

Stīga

 public final class String ievieš java.io.Serializable, Comparable, CharSequence {... 

Vesels skaitlis

 publiskās fināla klases vesels skaitlis pagarina skaitļu ieviešanu Salīdzināms {… 

Dubultā

 publiskā fināla klase Dubultā pagarina Skaitļu īstenošanas iespējas Salīdzināms 

Ir daudz citu. Es iesaku jums izpētīt Java pamatklases, lai uzzinātu to svarīgos modeļus un jēdzienus.

Piedalieties salīdzināmās saskarnes izaicinājumā!

Pārbaudiet, ko esat iemācījies, noskaidrojot šī koda izvadi. Atcerieties, ka jūs vislabāk uzzināsiet, ja pats atrisināsiet šo izaicinājumu, tikai to izpētot. Kad esat saņēmis atbildi, varat pārbaudīt atbildi zemāk. Varat arī veikt savus testus, lai pilnībā pārņemtu jēdzienus.

 public class SortComparableChallenge {public static void main (String ... doYourBest) {Set set = new TreeSet (); set.add (jauns Simpsons ("Homer")); set.add (jauns Simpsons ("Marge")); set.add (jauns Simpsons ("Lisa")); set.add (jauns Simpsons ("Bart")); set.add (jauns Simpsons ("Megija")); Sarakstu saraksts = new ArrayList (); list.addAll (kopa); Kolekcijas.reverss (saraksts); list.forEach (System.out :: println); } statiskā klase Simpsons ievieš Salīdzināms {String name; publiskais Simpsons (virknes nosaukums) {this.name = name; } public int salīdzinātTo (Simpson simpson) {return simpson.name.compareTo (this.name); } public String toString () {return this.name; }}} 

Kura ir šī koda izeja?

 A) Bārts Homērs Liza Megija Mārdža B) Megija Bāra Liza Mardže Homēra