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.


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