Guide til Java 8 Comparator. Sammenligning ()
1. Oversikt
Java 8 introduserte flere forbedringer til Komparator grensesnitt, inkludert en håndfull statiske funksjoner som er til stor nytte når du kommer med en sorteringsrekkefølge for samlinger.
Java 8 lambdas kan utnyttes effektivt med Komparator grensesnitt også. En detaljert forklaring på lambdas og Komparator finner du her, og en kronikk om sortering og anvendelser av Komparator finner du her.
I denne veiledningen, vi vil utforske flere funksjoner introdusert for Komparator grensesnitt i Java 8.
2. Komme i gang
2.1. Eksempel på bønneklasse
For eksemplene i denne artikkelen, la oss lage en Ansatt bønne og bruk feltene for sammenligning og sortering:
offentlig klasse ansatt {strengnavn; int alder; dobbel lønn; lang mobil; // konstruktører, getters & setters}
2.2. Våre testdata
La oss også lage en rekke ansatte som vil bli brukt til å lagre resultatene av vår type i forskjellige testsaker gjennom hele artikkelen:
ansatte = ny ansatt [] {...};
Den første bestillingen av elementer av ansatte vil være:
[Ansatt (navn = John, alder = 25, lønn = 3000.0, mobil = 9922001), Ansatt (navn = Ess, alder = 22, lønn = 2000.0, mobil = 5924001), Ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401)]
Gjennom artikkelen vil vi sortere ovenfor Ansatt array ved hjelp av forskjellige funksjoner.
For testhevdinger bruker vi et sett med forhåndssorterte matriser som vi vil sammenligne med sorteringsresultatene (dvs. ansatte array) for forskjellige scenarier.
La oss erklære noen av disse matriser:
@Før offentlig ugyldig initData () {sortedEmployeesByName = ny ansatt [] {...}; sortedEmployeesByNameDesc = ny ansatt [] {...}; sortedEmployeesByAge = ny ansatt [] {...}; // ...}
Som alltid, er du velkommen til å henvise GitHub-lenken vår for den fullstendige koden.
3. Bruke Comparator. Sammenligning
Denne delen dekker varianter av Comparator. Sammenligning statisk funksjon.
3.1. Nøkkelvelgervariant
De Comparator. Sammenligning statisk funksjon godtar en sorteringsnøkkel Funksjon og returnerer a Komparator for typen som inneholder sorteringsnøkkelen:
statisk Sammenligning av komparator (FunksjonstastExtractor)
For å se dette i aksjon, la oss bruke Navn felt i Ansatt som sorteringsnøkkel og passerer metodens referanse som et argument av typen Funksjon. De Komparator returneres fra det samme brukes til sortering:
@Test offentlig ugyldig nårComparing_thenSortedByName () {Comparator ansatteNameComparator = Comparator.comparing (ansatt :: getName); Arrays.sort (ansatte, ansattNameComparator); assertTrue (Arrays.equals (ansatte, sortertEmployeesByName)); }
Som du kan se, er ansatte matriseverdier sorteres etter navn som et resultat av sorteringen:
[Ansatt (navn = Ess, alder = 22, lønn = 2000.0, mobil = 5924001), Ansatt (navn = John, alder = 25, lønn = 3000.0, mobil = 9922001), Ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401)]
3.2. Nøkkelvelger og Komparator Variant
Det er et annet alternativ som muliggjør overstyring av den naturlige rekkefølgen av sorteringsnøkkelen ved å oppgi Komparator som oppretter en tilpasset bestilling for sorteringsnøkkelen:
statisk sammenligning av komparator (FunksjonstastExtractor, Comparator keyComparator)
La oss endre testen ovenfor, overstyre den naturlige sorteringsrekkefølgen etter Navn felt ved å tilby en Komparator for å sortere navnene i synkende rekkefølge som det andre argumentet til Comparator. Sammenligning:
@Test offentlig ugyldig nårComparingWithComparator_thenSortedByNameDesc () {Comparator medarbeidernavnComparator = Comparator.comparing (Ansatt :: getName, (s1, s2) -> {return s2.compareTo (s1);}); Arrays.sort (ansatte, ansattNameComparator); assertTrue (Arrays.equals (ansatte, sortertEmployeesByNameDesc)); }
Som du kan se, blir resultatene sortert i synkende rekkefølge etter Navn:
[Ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401), Ansatt (navn = John, alder = 25, lønn = 3000,0, mobil = 9922001), Ansatt (navn = Ess, alder = 22, lønn = 2000.0, mobil = 5924001)]
3.3. Ved hjelp av Comparator. Omvendt
Når påkalt på en eksisterende Komparator, forekomstmetoden Comparator. Omvendt returnerer en ny Komparator som reverserer sorteringsrekkefølgen til originalen.
La oss bruke Komparator som sorterer de ansatte etter Navn og omvendt det slik at ansatte blir sortert i fallende rekkefølge av Navn:
@Test offentlig ugyldig nårReversed_thenSortedByNameDesc () {Comparator ansatteNameComparator = Comparator.comparing (ansatt :: getName); Comparator medarbeidernavnComparatorReversed = ansattnavnComparator.reversed (); Arrays.sort (ansatte, ansattNameComparatorReversed); assertTrue (Arrays.equals (ansatte, sortertEmployeesByNameDesc)); }
Resultatene er sortert i synkende rekkefølge etter Navn:
[Ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401), Ansatt (navn = John, alder = 25, lønn = 3000,0, mobil = 9922001), Ansatt (navn = Ess, alder = 22, lønn = 2000.0, mobil = 5924001)]
3.4. Ved hjelp av Comparator.comparingInt
Det er også en funksjon Comparator.comparingInt som gjør det samme som Comparator. Sammenligning, men det tar bare int velgerne. La oss prøve dette med et eksempel der vi bestiller ansatte av alder:
@Test offentlig ugyldig nårComparingInt_thenSortedByAge () {Comparator employeeAgeComparator = Comparator.comparingInt (Ansatt :: getAge); Arrays.sort (ansatte, ansatteAgeComparator); assertTrue (Arrays.equals (ansatte, sortertEmployeesByAge)); }
La oss se hvordan ansatte arrayverdier blir ordnet etter sorteringen:
[Ansatt (navn = Ess, alder = 22, lønn = 2000.0, mobil = 5924001), Ansatt (navn = John, alder = 25, lønn = 3000.0, mobil = 9922001), Ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401)]
3.5. Ved hjelp av Comparator.comparingLong
Ligner på det vi gjorde for int tastene, la oss se et eksempel med Comparator.comparingLong å vurdere en sorteringsnøkkel av typen lang ved å bestille ansatte array av mobil felt:
@Test offentlig ugyldig nårComparingLong_thenSortedByMobile () {Comparator ansatteMobileComparator = Comparator.comparingLong (Ansatt :: getMobile); Arrays.sort (ansatte, ansatteMobileComparator); assertTrue (Arrays.equals (ansatte, sortertMedarbeidereByMobile)); }
La oss se hvordan ansatte arrayverdier blir ordnet etter sorteringen med mobil som nøkkelen:
[Ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401), Ansatt (navn = Ess, alder = 22, lønn = 2000,0, mobil = 5924001), Ansatt (navn = John, alder = 25, lønn = 3000,0, mobil = 9922001)]
3.6. Ved hjelp av Comparator.comparingDouble
Igjen, lik det vi gjorde for int og lang tastene, la oss se et eksempel med Comparator.comparingDouble å vurdere en sorteringsnøkkel av typen dobbelt ved å bestille ansatte array av lønn felt:
@Test offentlig ugyldig nårComparingDouble_thenSortedBySalary () {Comparator employeeSalaryComparator = Comparator.comparingDouble (Ansatt :: getSalary); Arrays.sort (ansatte, ansatteSalaryComparator); assertTrue (Arrays.equals (ansatte, sortertAnsatteBySalary)); }
La oss se hvordan ansatte arrayverdier blir ordnet etter sorteringen med lønn som sorteringstast:
[Ansatt (navn = Ess, alder = 22, lønn = 2000.0, mobil = 5924001), Ansatt (navn = John, alder = 25, lønn = 3000.0, mobil = 9922001), Ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401)]
4. Vurderer naturlig orden i Komparator
Den naturlige ordenen er definert av oppførselen til Sammenlignelig grensesnittimplementering. Mer informasjon om forskjellen mellom Komparator og bruk av Sammenlignelig grensesnitt kan bli funnet i denne artikkelen.
La oss implementere Sammenlignelig i vår Ansatt klasse slik at vi kan prøve naturlig bestilling og omvendt rekkefølge funksjonene til Komparator grensesnitt:
offentlig klasse Ansatt implementerer sammenlignbar {// ... @Override public int CompareTo (Employee argEmployee) {return name.compareTo (argEmployee.getName ()); }}
4.1. Bruke naturlig orden
De naturlig bestilling funksjonen returnerer Komparator for returtypen nevnt i signaturen:
statisk Komparator naturlig bestilling ()
Gitt den ovennevnte logikken for å sammenligne ansatte basert på Navn felt, la oss bruke denne funksjonen for å oppnå til a Komparator som sorterer ansatte array i naturlig rekkefølge:
@Test offentlig ugyldig nårNaturalOrder_thenSortedByName () {Comparator employeeNameComparator = Comparator. naturlig bestilling (); Arrays.sort (ansatte, ansattNameComparator); assertTrue (Arrays.equals (ansatte, sortertEmployeesByName)); }
La oss se hvordan ansatte arrayverdier er ordnet etter sorteringen:
[Ansatt (navn = Ess, alder = 22, lønn = 2000.0, mobil = 5924001), Ansatt (navn = John, alder = 25, lønn = 3000.0, mobil = 9922001), Ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401)]
4.2. Bruke omvendt naturlig orden
Lik naturlig bestilling, la oss bruke omvendt rekkefølge metode for å generere en Komparator som vil gi en omvendt rekkefølge på ansatte til den i naturlig bestilling eksempel:
@Test offentlig ugyldig nårReverseOrder_thenSortedByNameDesc () {Comparator employeeNameComparator = Comparator. omvendt rekkefølge(); Arrays.sort (ansatte, ansattNameComparator); assertTrue (Arrays.equals (ansatte, sortertEmployeesByNameDesc)); }
La oss se hvordan ansatte arrayverdier blir ordnet etter sorteringen:
[Ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401), Ansatt (navn = John, alder = 25, lønn = 3000,0, mobil = 9922001), Ansatt (navn = Ess, alder = 22, lønn = 2000.0, mobil = 5924001)]
5. Vurderer nullverdier i komparatoren
Denne delen dekker funksjoner nullsFirst og nullSiste, som vurderer null verdier i bestilling og beholder null verdier i begynnelsen eller slutten av bestillingssekvensen.
5.1. Vurderer Null First
La oss tilfeldig sette inn null verdier i ansatte matrise:
[Ansatt (navn = John, alder = 25, lønn = 3000,0, mobil = 9922001), null, ansatt (navn = ess, alder = 22, lønn = 2000,0, mobil = 5924001), null, ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401)]
De nullsFirst funksjonen returnerer a Komparator som holder alt null i begynnelsen av bestillingssekvensen:
@Test offentlig ugyldig nårNullsFirst_thenSortedByNameWithNullsFirst () {Comparator employeeNameComparator = Comparator.comparing (Ansatt :: getName); Comparator employeeNameComparator_nullFirst = Comparator.nullsFirst (medarbeidernavnComparator); Arrays.sort (ansatteArrayWithNulls, ansattnavnComparator_nullFirst); assertTrue (Arrays.equals (ansatteArrayWithNulls, sortertAnsatteArray_WithNullsFirst)); }
La oss se hvordan ansatte arrayverdier er ordnet etter sorteringen:
[null, null, ansatt (navn = ess, alder = 22, lønn = 2000.0, mobil = 5924001), ansatt (navn = John, alder = 25, lønn = 3000,0, mobil = 9922001), ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401)]
5.2. Vurderer Null Last
De nullSiste funksjonen returnerer a Komparator som holder alt null på slutten av bestillingssekvensen:
@Test offentlig ugyldig nårNullsLast_thenSortedByNameWithNullsLast () {Comparator medarbeidernavnComparator = Comparator.comparing (Ansatt :: getName); Comparator employeeNameComparator_nullLast = Comparator.nullsLast (medarbeidernavnComparator); Arrays.sort (ansatteArrayWithNulls, ansattnavnComparator_nullLast); assertTrue (Arrays.equals (ansatteArrayWithNulls, sortertEmployeesArray_WithNullsLast)); }
La oss se hvordan ansatte arrayverdier blir ordnet etter sorteringen:
[Ansatt (navn = Ess, alder = 22, lønn = 2000.0, mobil = 5924001), Ansatt (navn = John, alder = 25, lønn = 3000.0, mobil = 9922001), Ansatt (navn = Keith, alder = 35, lønn = 4000.0, mobil = 3924401), null, null]
6. Bruke Comparator.thenComparing
De deretter sammenligne funksjonen lar deg sette opp leksikografisk rekkefølge av verdier ved å tilordne flere sorteringstaster i en bestemt sekvens.
La oss vurdere et annet utvalg av Ansatt klasse:
someMoreEmployees = ny ansatt [] {...};
Vurder følgende sekvens av elementer i matrisen ovenfor:
[Ansatt (navn = Jake, alder = 25, lønn = 3000.0, mobil = 9922001), Ansatt (navn = Jake, alder = 22, lønn = 2000.0, mobil = 5924001), Ansatt (navn = Ess, alder = 22, lønn = 3000.0, mobil = 6423001), Ansatt (navn = Keith, alder = 35, lønn = 4000.0, mobil = 3924401)]
La oss skrive en sekvens av sammenligninger som alder etterfulgt av Navn og se rekkefølgen på denne matrisen:
@Test offentlig ugyldig nårThenComparing_thenSortedByAgeName () {Comparator employee_Age_Name_Comparator = Comparator.comparing (Employee :: getAge) .thenComparing (Employee :: getName); Arrays.sort (noenMoreEmployees, ansatte_Age_Name_Comparator); assertTrue (Arrays.equals (someMoreEmployees, sortedEmployeesByAgeName)); }
Her vil bestillingen bli gjort av alder, og for verdiene med det samme alder, bestilling vil bli gjort av Navn. La oss observere dette i sekvensen vi mottar etter sortering:
[Ansatt (navn = Ess, alder = 22, lønn = 3000.0, mobil = 6423001), Ansatt (navn = Jake, alder = 22, lønn = 2000.0, mobil = 5924001), Ansatt (navn = Jake, alder = 25, lønn = 3000,0, mobil = 9922001), Ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401)]
La oss bruke den andre versjonen av deretter sammenligne det er deretterComparingInt, ved å endre den leksikografiske sekvensen til Navn etterfulgt av alder:
@Test offentlig ugyldig nårThenComparing_thenSortedByNameAge () {Comparator medarbeider_Navn_Age_Comparator = Comparator.comparing (ansatt :: getName) .thenComparingInt (ansatt :: getAge); Arrays.sort (someMoreEmployees, employee_Name_Age_Comparator); assertTrue (Arrays.equals (someMoreEmployees, sortedEmployeesByNameAge)); }
La oss se hvordan ansatte arrayverdier er ordnet etter sorteringen:
[Ansatt (navn = Ess, alder = 22, lønn = 3000.0, mobil = 6423001), Ansatt (navn = Jake, alder = 22, lønn = 2000.0, mobil = 5924001), Ansatt (navn = Jake, alder = 25, lønn = 3000,0, mobil = 9922001), Ansatt (navn = Keith, alder = 35, lønn = 4000,0, mobil = 3924401)]
Tilsvarende er det funksjoner deretterComparingLong og deretterComparingDouble for bruk lang og dobbelt sorteringstaster.
7. Konklusjon
Denne artikkelen er en guide til flere funksjoner introdusert i Java 8 for Komparator grensesnitt.
Som vanlig kan kildekoden finnes på Github.