Guide til Java 8 Comparator. Sammenligning ()

1. Oversigt

Java 8 introducerede flere forbedringer af Komparator interface, herunder en håndfuld statiske funktioner, der er til stor nytte, når man kommer med en sorteringsrækkefølge for samlinger.

Java 8 lambdas kan udnyttes effektivt med Komparator interface også. En detaljeret forklaring på lambdas og Komparator kan findes her og en krønike om sortering og anvendelse af Komparator kan findes her.

I denne vejledning vi vil undersøge flere funktioner, der er introduceret til Komparator interface i Java 8.

2. Kom godt i gang

2.1. Eksempel på bønneklasse

Lad eksemplerne i denne artikel oprette en Medarbejder bønne og bruge dens felter til sammenligning og sortering:

offentlig klassemedarbejder {Strenge navn; int alder dobbelt løn lang mobil; // konstruktører, getters & settere}

2.2. Vores testdata

Lad os også oprette en række medarbejdere, der vil blive brugt til at gemme resultaterne af vores type i forskellige testsager gennem hele artiklen:

medarbejdere = ny medarbejder [] {...};

Den indledende rækkefølge af elementer af medarbejdere vil være:

[Medarbejder (navn = John, alder = 25, løn = 3000.0, mobil = 9922001), Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001), Medarbejder (navn = Keith, alder = 35, løn = 4000,0, mobil = 3924401)]

I hele artiklen sorterer vi ovenfor Medarbejder array ved hjælp af forskellige funktioner.

Til testpåstande bruger vi et sæt præ-sorterede arrays, som vi sammenligner med vores sorteringsresultater (dvs. medarbejdere array) til forskellige scenarier.

Lad os erklære et par af disse arrays:

@Før offentlige ugyldige initData () {sortedEmployeesByName = ny medarbejder [] {...}; sortedEmployeesByNameDesc = ny medarbejder [] {...}; sortedEmployeesByAge = ny medarbejder [] {...}; // ...}

Som altid er du velkommen til at henvise vores GitHub-link til den komplette kode.

3. Brug Comparator. Sammenligning

Dette afsnit dækker varianter af Comparator. Sammenligning statisk funktion.

3.1. Tastevælgervariant

Det Comparator. Sammenligning statisk funktion accepterer en sorteringstast Fungere og returnerer a Komparator for den type, der indeholder sorteringsnøglen:

statisk  Sammenligning af komparator (FunktionstastExtractor)

For at se dette i aktion, lad os bruge navn felt i Medarbejder som sorteringsnøgle og videregive dens metodehenvisning som argument af typen Fungere. Det Komparator returneret fra det samme bruges til sortering:

@Test offentlig ugyldig nårComparing_thenSortedByName () {Comparator medarbejdernavnComparator = Comparator.comparing (Medarbejder :: getName); Arrays.sort (medarbejdere, medarbejdernavnComparator); assertTrue (Arrays.equals (medarbejdere, sorteretEmployeesByName)); }

Som du kan se, er medarbejdere matrixværdier sorteres efter navn som et resultat af sorteringen:

[Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001), Medarbejder (navn = John, alder = 25, løn = 3000.0, mobil = 9922001), Medarbejder (navn = Keith, alder = 35, løn = 4000,0, mobil = 3924401)] 

3.2. Tastevælger og Komparator Variant

Der er en anden mulighed, der letter tilsidesættelse af den naturlige rækkefølge af sorteringsnøglen ved at angive Komparator der opretter en brugerdefineret rækkefølge for sorteringsnøglen:

statisk sammenligning af komparator (funktionstastExtractor, komparatortastKomparator)

Lad os ændre testen ovenfor og tilsidesætte den naturlige rækkefølge efter sortering efter navn felt ved at levere en Komparator for at sortere navnene i faldende rækkefølge som det andet argument til Comparator. Sammenligning:

@Test offentlig ugyldig nårComparingWithComparator_thenSortedByNameDesc () {Comparator medarbejdernavnComparator = Comparator.comparing (Medarbejder :: getName, (s1, s2) -> {return s2.compareTo (s1);}); Arrays.sort (medarbejdere, medarbejdernavnComparator); assertTrue (Arrays.equals (medarbejdere, sorteretEmployeesByNameDesc)); }

Som du kan se, sorteres resultaterne i faldende rækkefølge efter navn:

[Medarbejder (navn = Keith, alder = 35, løn = 4000,0, mobil = 3924401), Medarbejder (navn = John, alder = 25, løn = 3000,0, mobil = 9922001), Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001)]

3.3. Ved brug af Comparator. Omvendt

Når påberåbt sig en eksisterende Komparator, instansmetoden Comparator. Omvendt returnerer et nyt Komparator der vender originalens sorteringsrækkefølge.

Lad os bruge Komparator der sorterer medarbejderne efter navn og baglæns det, så medarbejderne sorteres i faldende rækkefølge efter navn:

@Test offentlig ugyldig nårReversed_thenSortedByNameDesc () {Comparator medarbejdernavnComparator = Comparator.comparing (Medarbejder :: getName); Comparator medarbejdernavnComparatorReversed = medarbejdernavnComparator.omvendt (); Arrays.sort (medarbejdere, medarbejdernavnComparatorReversed); assertTrue (Arrays.equals (medarbejdere, sorteretEmployeesByNameDesc)); }

Resultaterne sorteres i faldende rækkefølge efter navn:

[Medarbejder (navn = Keith, alder = 35, løn = 4000,0, mobil = 3924401), Medarbejder (navn = John, alder = 25, løn = 3000,0, mobil = 9922001), Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001)]

3.4. Ved brug af Comparator.comparingInt

Der er også en funktion Comparator.comparingInt der gør det samme som Comparator. Sammenligning, men det tager kun int vælgere. Lad os prøve dette med et eksempel, hvor vi bestiller medarbejdere ved alder:

@Test offentlig ugyldig nårComparingInt_thenSortedByAge () {Comparator employeeAgeComparator = Comparator.comparingInt (Medarbejder :: getAge); Arrays.sort (medarbejdere, medarbejderAgeComparator); assertTrue (Arrays.equals (medarbejdere, sorteretMedarbejdereByAge)); }

Lad os se, hvordan medarbejdere matrixværdier er sorteret efter sorteringen:

[Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001), Medarbejder (navn = John, alder = 25, løn = 3000.0, mobil = 9922001), Medarbejder (navn = Keith, alder = 35, løn = 4000,0, mobil = 3924401)]

3.5. Ved brug af Comparator.comparingLong

Svarende til hvad vi gjorde for int nøgler, lad os se et eksempel ved hjælp af Comparator.comparingLong at overveje en slags nøgle af typen lang ved at bestille medarbejdere array af mobil Mark:

@Test offentlig ugyldig nårComparingLong_thenSortedByMobile () {Comparator medarbejderMobileComparator = Comparator.comparingLong (Medarbejder :: getMobile); Arrays.sort (medarbejdere, medarbejderMobileComparator); assertTrue (Arrays.equals (medarbejdere, sorteretMedarbejdereByMobile)); }

Lad os se, hvordan medarbejdere matrixværdier ordnes efter sorteringen med mobil som nøgle:

[Medarbejder (navn = Keith, alder = 35, løn = 4000,0, mobil = 3924401), Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001), Medarbejder (navn = John, alder = 25, løn = 3000,0, mobil = 9922001)]

3.6. Ved brug af Comparator.comparingDouble

Igen svarende til det, vi gjorde for int og lang nøgler, lad os se et eksempel ved hjælp af Comparator.comparingDouble at overveje en slags nøgle af typen dobbelt ved at bestille medarbejdere array af løn Mark:

@Test offentlig ugyldig nårComparingDouble_thenSortedBySalary () {Comparator employeeSalaryComparator = Comparator.comparingDouble (Medarbejder :: getSalary); Arrays.sort (medarbejdere, medarbejderSalaryComparator); assertTrue (Arrays.equals (medarbejdere, sorteretEmployeesBySalary)); }

Lad os se, hvordan medarbejdere array-værdier ordnes efter sorteringen med løn som sorteringstast:

[Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001), Medarbejder (navn = John, alder = 25, løn = 3000.0, mobil = 9922001), Medarbejder (navn = Keith, alder = 35, løn = 4000,0, mobil = 3924401)]

4. I betragtning af naturlig orden i Komparator

Den naturlige orden er defineret af adfærden hos Sammenlignelig interface implementering. Flere oplysninger om forskellen mellem Komparator og anvendelser af Sammenlignelig interface findes i denne artikel.

Lad os implementere Sammenlignelig i vores Medarbejder klasse, så vi kan prøve naturlig bestilling og omvendt rækkefølge funktionerne i Komparator grænseflade:

offentlig klasse Medarbejderimplementeringer Sammenlignelig {// ... @ Override public int comparTo (Medarbejder argEmployee) {return name.compareTo (argEmployee.getName ()); }}

4.1. Brug af naturlig orden

Det naturlig bestilling funktion returnerer Komparator for den returtype, der er nævnt i signaturen:

statisk  Komparator naturlig bestilling ()

Givet ovenstående logik til at sammenligne medarbejdere baseret på navn felt, lad os bruge denne funktion til at opnå til a Komparator der sorterer medarbejdere matrix i naturlig rækkefølge:

@Test offentlig ugyldig nårNaturalOrder_thenSortedByName () {Comparator medarbejderNameComparator = Comparator. naturlig bestilling (); Arrays.sort (medarbejdere, medarbejdernavnComparator); assertTrue (Arrays.equals (medarbejdere, sorteretEmployeesByName)); }

Lad os se, hvordan medarbejdere matrixværdier er sorteret efter sorteringen:

[Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001), Medarbejder (navn = John, alder = 25, løn = 3000.0, mobil = 9922001), Medarbejder (navn = Keith, alder = 35, løn = 4000,0, mobil = 3924401)]

4.2. Brug af omvendt naturlig orden

Svarende til naturlig bestilling, lad os bruge omvendt rækkefølge metode til at generere en Komparator som vil producere en omvendt rækkefølge af medarbejdere til den i naturlig bestilling eksempel:

@Test offentlig ugyldig nårReverseOrder_thenSortedByNameDesc () {Comparator medarbejdernavnComparator = Komparator. omvendt rækkefølge(); Arrays.sort (medarbejdere, medarbejdernavnComparator); assertTrue (Arrays.equals (medarbejdere, sorteretEmployeesByNameDesc)); }

Lad os se, hvordan medarbejdere matrixværdier er sorteret efter sorteringen:

[Medarbejder (navn = Keith, alder = 35, løn = 4000,0, mobil = 3924401), Medarbejder (navn = John, alder = 25, løn = 3000,0, mobil = 9922001), Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001)]

5. Overvejer nulværdier i komparator

Dette afsnit dækker funktioner nullsFørst og nullsLast, som overvejer nul værdier i rækkefølge og opbevar nul værdier i begyndelsen eller slutningen af ​​rækkefølgen.

5.1. I betragtning af Null First

Lad os tilfældigt indsætte nul værdier i medarbejdere matrix:

[Medarbejder (navn = John, alder = 25, løn = 3000.0, mobil = 9922001), null, Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001), null, Medarbejder (navn = Keith, alder = 35, løn = 4000,0, mobil = 3924401)]

Det nullsFørst funktion returnerer a Komparator der holder alt nul i begyndelsen af ​​rækkefølgen:

@Test offentlig ugyldig nårNullsFirst_thenSortedByNameWithNullsFirst () {Comparator medarbejdernavnComparator = Comparator.comparing (Medarbejder :: getName); Comparator medarbejdernavnComparator_nullFirst = Comparator.nullsFirst (medarbejdernavnComparator); Arrays.sort (medarbejderArrayWithNulls, medarbejdernavnComparator_nullFirst); assertTrue (Arrays.equals (workersArrayWithNulls, sortedEmployeesArray_WithNullsFirst)); }

Lad os se, hvordan medarbejdere matrixværdier er sorteret efter sorteringen:

[null, null, Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001), Medarbejder (navn = John, alder = 25, løn = 3000.0, mobil = 9922001), Medarbejder (navn = Keith, alder = 35, løn = 4000,0, mobil = 3924401)]

5.2. I betragtning af Null Last

Det nullsLast funktion returnerer a Komparator der holder alt nul i slutningen af ​​rækkefølgen:

@Test offentlig ugyldig nårNullsLast_thenSortedByNameWithNullsLast () {Comparator medarbejdernavnComparator = Comparator.comparing (Medarbejder :: getName); Comparator medarbejdernavnComparator_nullLast = Comparator.nullsLast (medarbejdernavnComparator); Arrays.sort (medarbejderArrayWithNulls, medarbejdernavnComparator_nullLast); assertTrue (Arrays.equals (medarbejderArrayWithNulls, sorteretEmployeesArray_WithNullsLast)); }

Lad os se, hvordan medarbejdere matrixværdier er sorteret efter sorteringen:

[Medarbejder (navn = Ess, alder = 22, løn = 2000.0, mobil = 5924001), Medarbejder (navn = John, alder = 25, løn = 3000.0, mobil = 9922001), Medarbejder (navn = Keith, alder = 35, løn = 4000.0, mobil = 3924401), null, null]

6. Brug Comparator. DerefterComparing

Det derefter Sammenligning -funktion lader dig opsætte leksikografisk rækkefølge af værdier ved at tilvejebringe flere sorteringstaster i en bestemt sekvens.

Lad os overveje en anden række af Medarbejder klasse:

someMoreEmployees = ny medarbejder [] {...};

Overvej følgende rækkefølge af elementer i ovenstående array:

[Medarbejder (navn = Jake, alder = 25, løn = 3000.0, mobil = 9922001), Medarbejder (navn = Jake, alder = 22, løn = 2000.0, mobil = 5924001), Medarbejder (navn = Ace, alder = 22, løn = 3000.0, mobil = 6423001), Medarbejder (navn = Keith, alder = 35, løn = 4000.0, mobil = 3924401)]

Lad os skrive en sekvens af sammenligninger som alder efterfulgt af navn og se rækkefølgen af ​​denne matrix:

@Test offentlig ugyldig nårThenComparing_thenSortedByAgeName () {Comparator medarbejder_Age_Name_Comparator = Comparator.comparing (Medarbejder :: getAge) .thenComparing (Medarbejder :: getName); Arrays.sort (nogleMereEmployees, medarbejder_Age_navn_Comparator); assertTrue (Arrays.equals (someMoreEmployees, sortedEmployeesByAgeName)); }

Her vil bestillingen blive udført af alderog for værdierne med det samme alder, bestilling foretages af navn. Lad os observere dette i den rækkefølge, vi modtager efter sortering:

[Medarbejder (navn = Ess, alder = 22, løn = 3000.0, mobil = 6423001), Medarbejder (navn = Jake, alder = 22, løn = 2000.0, mobil = 5924001), Medarbejder (navn = Jake, alder = 25, løn = 3000.0, mobil = 9922001), Medarbejder (navn = Keith, alder = 35, løn = 4000.0, mobil = 3924401)]

Lad os bruge den anden version af derefter Sammenligning det er derefterComparingIntved at ændre den leksikografiske rækkefølge til navn efterfulgt af alder:

@Test offentlig ugyldig nårThenComparing_thenSortedByNameAge () {Comparator medarbejder_Navn_Age_Comparator = Comparator.comparing (Medarbejder :: getName) .thenComparingInt (Medarbejder :: getAge); Arrays.sort (nogleMereEmployees, medarbejder_Navn_Age_Comparator); assertTrue (Arrays.equals (someMoreEmployees, sortedEmployeesByNameAge)); }

Lad os se, hvordan medarbejdere matrixværdier er sorteret efter sorteringen:

[Medarbejder (navn = Ess, alder = 22, løn = 3000.0, mobil = 6423001), Medarbejder (navn = Jake, alder = 22, løn = 2000.0, mobil = 5924001), Medarbejder (navn = Jake, alder = 25, løn = 3000.0, mobil = 9922001), Medarbejder (navn = Keith, alder = 35, løn = 4000.0, mobil = 3924401)]

Tilsvarende er der funktioner derefterComparingLong og derefterComparingDouble til brug lang og dobbelt sorteringstaster.

7. Konklusion

Denne artikel er en guide til flere funktioner introduceret i Java 8 til Komparator interface.

Som normalt kan kildekoden findes på Github.