Sammenligning og sammenlignbar i Java

1. Introduksjon

Sammenligning i Java er ganske enkelt - til de ikke er det.

Når vi arbeider med tilpassede typer, eller prøver å sammenligne objekter som ikke er direkte sammenlignbare, må vi bruke en sammenligningsstrategi. Vi kan bygge en enkelt, men ved å bruke Komparator eller Sammenlignelig grensesnitt.

2. Sette opp eksemplet

La oss ta et eksempel på et fotballag - hvor vi vil stille opp spillerne etter rangering.

Vi begynner med å lage en enkel Spiller klasse:

offentlig klassespiller {private int rangering; privat strengnavn; privat alder; // constructor, getters, setters}

La oss deretter lage en PlayerSorter klasse for å lage samlingen vår og gjøre et forsøk på å sortere den ved hjelp av Collections.sort:

public static void main (String [] args) {List footballTeam = new ArrayList (); Spiller spiller1 = ny spiller (59, "John", 20); Player player2 = ny spiller (67, "Roger", 22); Spiller spiller3 = ny spiller (45, "Steven", 24); footballTeam.add (spiller1); footballTeam.add (spiller2); footballTeam.add (spiller3); System.out.println ("Før sortering:" + footballTeam); Collections.sort (footballTeam); System.out.println ("Etter sortering:" + footballTeam); } 

Her, som forventet, resulterer dette i en kompileringsfeil:

Metodesorteringen (Liste) i typen Samlinger gjelder ikke for argumentene (ArrayList)

La oss forstå hva vi gjorde galt her.

3. Sammenlignelig

Som navnet antyder, Sammenlignelig er et grensesnitt som definerer en strategi for å sammenligne et objekt med andre objekter av samme type. Dette kalles klassens “naturlige ordre”.

Følgelig, for å kunne sortere - må vi definere våre Spiller objekt som sammenlignbart ved å implementere Sammenlignelig grensesnitt:

public class Player implementer Comparable {// same as before @Override public int compareTo (Player otherPlayer) {return Integer.compare (getRanking (), otherPlayer.getRanking ()); }} 

Sorteringsrekkefølgen avgjøres av returverdien til sammenligne med()metode. De Heltall. Sammenligne (x, y) returnerer -1 hvis x er mindre enn y, returnerer 0 hvis de er like, og returnerer 1 ellers.

Metoden returnerer et tall som indikerer om objektet som sammenlignes er mindre enn, lik eller større enn objektet som sendes som et argument.

Endelig når vi kjører vår PlayerSorter nå kan vi se vår Spillere sortert etter rangering:

Før sortering: [John, Roger, Steven] Etter sortering: [Steven, John, Roger]

Nå som vi har en klar forståelse av naturlig bestilling med Sammenlignelig, la oss se hvordan vi kan bruke andre typer bestillinger, på en mer fleksibel måte enn å implementere et grensesnitt direkte.

4. Komparator

De Komparator grensesnitt definerer en sammenlign (arg1, arg2) metode med to argumenter som representerer sammenlignede objekter og fungerer på samme måte som Comparable.compareTo () metode.

4.1. Å skape Sammenligning

Å lage en Komparator, vi må implementere Komparator grensesnitt.

I vårt første eksempel oppretter vi en Komparator å bruke rangering attributt av Spiller å sortere spillerne:

offentlig klasse PlayerRankingComparator implementerer Comparator {@Override public int compare (Player firstPlayer, Player secondPlayer) {return Integer.compare (firstPlayer.getRanking (), secondPlayer.getRanking ()); }}

På samme måte kan vi lage en Komparator å bruke alder attributt av Spiller å sortere spillerne:

offentlig klasse PlayerAgeComparator implementerer Comparator {@Override public int compare (Player firstPlayer, Player secondPlayer) {return Integer.compare (firstPlayer.getAge (), secondPlayer.getAge ()); }}

4.2. Sammenligning i aksjon

For å demonstrere konseptet, la oss endre vårt PlayerSorter ved å introdusere et annet argument for Collections.sort-metoden som faktisk er forekomsten av Komparator vi vil bruke.

Ved å bruke denne tilnærmingen kan vi overstyre den naturlige rekkefølgen:

PlayerRankingComparator playerComparator = ny PlayerRankingComparator (); Collections.sort (footballTeam, playerComparator); 

La oss kjøre vår PlayerRankingSorter til se resultatet:

Før sortering: [John, Roger, Steven] Etter sortering etter rangering: [Steven, John, Roger]

Hvis vi ønsker en annen sorteringsrekkefølge, trenger vi bare å endre Komparator vi bruker:

PlayerAgeComparator playerComparator = ny PlayerAgeComparator (); Collections.sort (footballTeam, playerComparator);

Nå, når vi kjører vår PlayerAgeSorter, kan vi se en annen sorteringsrekkefølge etter alder:

Før sortering: [John, Roger, Steven] Etter sortering etter alder: [Roger, John, Steven]

4.3. Java 8 Sammenligning

Java 8 gir nye måter å definere på Sammenligning ved å bruke lambdauttrykk og sammenligne () statisk fabrikkmetode.

La oss se et raskt eksempel på hvordan du bruker et lambdauttrykk til å lage et Komparator:

Comparator byRanking = (Player player1, Player player2) -> Integer.compare (player1.getRanking (), player2.getRanking ());

De Comparator. Sammenligning metoden tar en metode som beregner egenskapen som skal brukes til å sammenligne varer, og returnerer en matching Komparator forekomst:

Comparator byRanking = Comparator .comparing (Player :: getRanking); Comparator byAge = Comparator .comparing (Player :: getAge);

Du kan utforske Java 8-funksjonaliteten grundig i vår guide for sammenligning av Java 8 Comparator.

5. Komparator vs. Sammenlignelig

De Sammenlignelig grensesnitt er et godt valg når det brukes til å definere standardbestilling eller med andre ord hvis det er den viktigste måten å sammenligne objekter på.

Så må vi spørre oss selv hvorfor bruke a Komparator hvis vi allerede har Sammenlignelig?

Det er flere grunner til at:

  • Noen ganger kan vi ikke endre kildekoden til klassen hvis objekter vi vil sortere, og dermed bruke Sammenlignelig umulig
  • Ved hjelp av Sammenligning lar oss unngå å legge til ekstra kode i domeneklassene våre
  • Vi kan definere flere forskjellige sammenligningsstrategier som ikke er mulig når du bruker Sammenlignelig

6. Unngå subtraksjonstrikset

I løpet av denne opplæringen brukte vi Integer.compare () metode for å sammenligne to heltall. Man kan argumentere for at vi i stedet bør bruke denne smarte one-liner:

Comparator comparator = (p1, p2) -> p1.getRanking () - p2.getRanking ();

Selv om det er mye mer kortfattet sammenlignet med andre løsninger, kan det være et offer for heltalloverløp i Java:

Player player1 = ny spiller (59, "John", Integer.MAX_VALUE); Player player2 = ny spiller (67, "Roger", -1); Liste spillere = Arrays.asList (player1, player2); players.sort (komparator);

Siden -1 er mye mindre enn Heltall.MAX_VALUE, "Roger" skulle komme før "John" i den sorterte samlingen. Imidlertid på grunn av heltalloverløp “Integer.MAX_VALUE - (-1)” vil være mindre enn null. Så, basert på Sammenligning / sammenlignbar kontrakt, den Heltall.MAX_VALUE er mindre enn -1, noe som åpenbart er feil.

Derfor, til tross for hva vi forventet, kommer "John" foran "Roger" i den sorterte samlingen:

assertEquals ("John", players.get (0) .getName ()); assertEquals ("Roger", players.get (1) .getName ());

7. Konklusjon

I denne opplæringen utforsket vi Sammenlignelig og Komparator grensesnitt og diskuterte forskjellene mellom dem.

For å forstå mer avanserte emner for sortering, sjekk ut våre andre artikler som Java 8 Comparator, Java 8 Comparison with Lambdas.

Og som vanlig kan kildekoden bli funnet på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found