Gids voor Java 8 Comparator.comparing ()

1. Overzicht

Java 8 introduceerde verschillende verbeteringen in het Comparator interface, inclusief een handvol statische functies die van groot nut zijn bij het bedenken van een sorteervolgorde voor verzamelingen.

Java 8-lambda's kunnen effectief worden gebruikt met de Comparator interface ook. Een gedetailleerde uitleg van lambda's en Comparator is hier te vinden, en een kroniek over sortering en toepassingen van Comparator vind je hier.

In deze tutorial we zullen verschillende functies onderzoeken die zijn geïntroduceerd voor het Comparator interface in Java 8.

2. Aan de slag

2.1. Proef de bonenklasse

Laten we voor de voorbeelden in dit artikel een Werknemer bean en gebruik zijn velden voor vergelijkings- en sorteerdoeleinden:

openbare klasse Medewerker {Stringnaam; int leeftijd; dubbel salaris; lang mobiel; // constructeurs, getters & setters}

2.2. Onze testgegevens

Laten we ook een reeks medewerkers maken die zullen worden gebruikt om de resultaten van ons type in verschillende testcases in het artikel op te slaan:

medewerkers = nieuwe medewerker [] {...};

De eerste ordening van elementen van medewerkers zal zijn:

[Medewerker (naam = John, leeftijd = 25, salaris = 3000.0, mobiel = 9922001), Medewerker (naam = Ace, leeftijd = 22, salaris = 2000.0, mobiel = 5924001), Medewerker (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401)]

In het hele artikel zullen we hierboven sorteren Werknemer array met verschillende functies.

Voor testbeweringen gebruiken we een set voorgesorteerde arrays die we zullen vergelijken met onze sorteerresultaten (d.w.z. de medewerkers array) voor verschillende scenario's.

Laten we een paar van deze arrays verklaren:

@Before public void initData () {gesorteerdEmployeesByName = nieuwe werknemer [] {...}; gesorteerdEmployeesByNameDesc = nieuwe werknemer [] {...}; gesorteerdEmployeesByAge = nieuwe werknemer [] {...}; // ...}

Zoals altijd, kunt u onze GitHub-link raadplegen voor de volledige code.

3. Met behulp van Comparator.comparing

Dit gedeelte behandelt varianten van de Comparator.comparing statische functie.

3.1. Key Selector Variant

De Comparator.comparing statische functie accepteert een sorteersleutel Functie en retourneert een Comparator voor het type dat de sorteersleutel bevat:

statisch  Comparator vergelijken (Functietoets Extractor)

Om dit in actie te zien, gebruiken we de naam veld in Werknemer als de sorteersleutel en geef de methodeverwijzing door als een argument van het type Functie. De Comparator geretourneerd van hetzelfde wordt gebruikt voor het sorteren:

@Test openbare ongeldigheid whenComparing_thenSortedByName () {Comparator employeeNameComparator = Comparator.comparing (Employee :: getName); Arrays.sort (werknemers, employeeNameComparator); assertTrue (Arrays.equals (werknemers, gesorteerdEmployeesByName)); }

Zoals u kunt zien, is de medewerkers matrixwaarden worden op naam gesorteerd als resultaat van de sortering:

[Medewerker (naam = Ace, leeftijd = 22, salaris = 2000,0, mobiel = 5924001), Medewerker (naam = John, leeftijd = 25, salaris = 3000,0, mobiel = 9922001), Medewerker (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401)] 

3.2. Key Selector en Comparator Variant

Er is een andere optie die het opheffen van de natuurlijke volgorde van de sorteersleutel vergemakkelijkt door de Comparator die een aangepaste volgorde voor de sorteersleutel creëert:

statische Comparator-vergelijking (FunctietoetsExtractor, Comparator-toetsComparator)

Laten we de bovenstaande test aanpassen en de natuurlijke volgorde van sorteren opheffen door de naam veld door een Comparator voor het sorteren van de namen in aflopende volgorde als het tweede argument voor Comparator.comparing:

@Test openbare leegte whenComparingWithComparator_thenSortedByNameDesc () {Comparator employeeNameComparator = Comparator.comparing (Employee :: getName, (s1, s2) -> {return s2.compareTo (s1);}); Arrays.sort (werknemers, employeeNameComparator); assertTrue (Arrays.equals (werknemers, gesorteerdEmployeesByNameDesc)); }

Zoals u kunt zien, zijn de resultaten in aflopende volgorde gesorteerd op naam:

[Medewerker (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401), Medewerker (naam = John, leeftijd = 25, salaris = 3000.0, mobiel = 9922001), Medewerker (naam = Ace, leeftijd = 22, salaris = 2000.0, mobiel = 5924001)]

3.3. Gebruik makend van Comparator. Teruggedraaid

Wanneer aangeroepen op een bestaand Comparator, de instantiemethode Comparator. Teruggedraaid geeft een nieuw Comparator dat de sorteervolgorde van het origineel omkeert.

Laten we de Comparator dat sorteert de medewerkers op naam en omgekeerde zodat medewerkers worden gesorteerd in aflopende volgorde van de naam:

@Test openbaar ongeldig whenReversed_thenSortedByNameDesc () {Comparator employeeNameComparator = Comparator.comparing (Employee :: getName); Comparator employeeNameComparatorReversed = employeeNameComparator.reversed (); Arrays.sort (werknemers, employeeNameComparatorReversed); assertTrue (Arrays.equals (werknemers, gesorteerdEmployeesByNameDesc)); }

De resultaten zijn in aflopende volgorde gesorteerd op naam:

[Medewerker (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401), Medewerker (naam = John, leeftijd = 25, salaris = 3000.0, mobiel = 9922001), Medewerker (naam = Ace, leeftijd = 22, salaris = 2000.0, mobiel = 5924001)]

3.4. Gebruik makend van Comparator.comparingInt

Er is ook een functie Comparator.comparingInt wat hetzelfde doet als Comparator.comparing, maar het duurt maar int kiezers. Laten we dit proberen met een voorbeeld waar we bestellen medewerkers door leeftijd:

@Test openbare ongeldig whenComparingInt_thenSortedByAge () {Comparator employeeAgeComparator = Comparator.comparingInt (Employee :: getAge); Arrays.sort (medewerkers, employeeAgeComparator); assertTrue (Arrays.equals (werknemers, gesorteerdEmployeesByAge)); }

Laten we eens kijken hoe de medewerkers matrixwaarden zijn gerangschikt volgens de sortering:

[Medewerker (naam = Ace, leeftijd = 22, salaris = 2000,0, mobiel = 5924001), Medewerker (naam = John, leeftijd = 25, salaris = 3000,0, mobiel = 9922001), Medewerker (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401)]

3.5. Gebruik makend van Comparator.comparingLong

Net als waarvoor we deden int toetsen, laten we een voorbeeld bekijken met Comparator.comparingLong om een ​​soort sleutel van het type te overwegen lang door de medewerkers array door de mobiel veld:

@Test openbare leegte whenComparingLong_thenSortedByMobile () {Comparator employeeMobileComparator = Comparator.comparingLong (Employee :: getMobile); Arrays.sort (medewerkers, employeeMobileComparator); assertTrue (Arrays.equals (werknemers, gesorteerdEmployeesByMobile)); }

Laten we eens kijken hoe de medewerkers matrixwaarden worden gerangschikt na de sortering met mobiel als de sleutel:

[Medewerker (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401), Medewerker (naam = Ace, leeftijd = 22, salaris = 2000.0, mobiel = 5924001), Medewerker (naam = John, leeftijd = 25, salaris = 3000.0, mobiel = 9922001)]

3.6. Gebruik makend van Comparator.comparingDouble

Nogmaals, vergelijkbaar met waarvoor we deden int en lang toetsen, laten we een voorbeeld bekijken met Comparator.comparingDouble om een ​​soort sleutel van het type te overwegen dubbele door de medewerkers array door de salaris veld:

@Test openbare ongeldig whenComparingDouble_thenSortedBySalary () {Comparator employeeSalaryComparator = Comparator.comparingDouble (Employee :: getSalary); Arrays.sort (medewerkers, employeeSalaryComparator); assertTrue (Arrays.equals (werknemers, gesorteerdEmployeesBySalary)); }

Laten we eens kijken hoe de medewerkers matrixwaarden worden gerangschikt na de sortering met salaris als de sorteersleutel:

[Medewerker (naam = Ace, leeftijd = 22, salaris = 2000,0, mobiel = 5924001), Medewerker (naam = John, leeftijd = 25, salaris = 3000,0, mobiel = 9922001), Medewerker (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401)]

4. Overweeg natuurlijke orde in Comparator

De natuurlijke volgorde wordt bepaald door het gedrag van de Vergelijkbaar interface implementatie. Meer informatie over het verschil tussen Comparator en gebruik van de Vergelijkbaar interface is te vinden in dit artikel.

Laten we implementeren Vergelijkbaar in onze Werknemer klasse zodat we de natuurlijke orde en omgekeerde volgorde functies van de Comparator koppel:

openbare klasse Werknemer implementeert vergelijkbare {// ... @Override openbare int CompareTo (werknemer argEmployee) {return name.compareTo (argEmployee.getName ()); }}

4.1. Natuurlijke volgorde gebruiken

De natuurlijke orde functie geeft de Comparator voor het retourtype vermeld in de handtekening:

statisch  Comparator natuurlijk

Gezien de bovenstaande logica om werknemers te vergelijken op basis van naam veld, laten we deze functie gebruiken om een Comparator die de medewerkers array in natuurlijke volgorde:

@Test openbaar ongeldig whenNaturalOrder_thenSortedByName () {Comparator employeeNameComparator = Comparator. natuurlijke orde(); Arrays.sort (werknemers, employeeNameComparator); assertTrue (Arrays.equals (werknemers, gesorteerdEmployeesByName)); }

Laten we eens kijken hoe de medewerkers matrixwaarden zijn gerangschikt volgens de sortering:

[Medewerker (naam = Ace, leeftijd = 22, salaris = 2000,0, mobiel = 5924001), Medewerker (naam = John, leeftijd = 25, salaris = 3000,0, mobiel = 9922001), Medewerker (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401)]

4.2. Omgekeerde natuurlijke volgorde gebruiken

Gelijkwaardig aan natuurlijke orde, laten we de omgekeerde volgorde methode om een Comparator wat een omgekeerde volgorde van medewerkers naar die in de natuurlijke orde voorbeeld:

@Test openbaar ongeldig whenReverseOrder_thenSortedByNameDesc () {Comparator employeeNameComparator = Comparator. omgekeerde volgorde(); Arrays.sort (werknemers, employeeNameComparator); assertTrue (Arrays.equals (werknemers, gesorteerdEmployeesByNameDesc)); }

Laten we eens kijken hoe de medewerkers matrixwaarden zijn gerangschikt volgens de sortering:

[Medewerker (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401), Medewerker (naam = John, leeftijd = 25, salaris = 3000.0, mobiel = 9922001), Medewerker (naam = Ace, leeftijd = 22, salaris = 2000.0, mobiel = 5924001)]

5. Null-waarden overwegen in Comparator

Dit gedeelte behandelt functies nulls Eerste en nulls Laatste, die overwegen nul waarden bij het bestellen en houd de nul waarden aan het begin of einde van de volgorde van bestellen.

5.1. Overweeg eerst Null

Laten we willekeurig invoegen nul waarden in medewerkers matrix:

[Medewerker (naam = John, leeftijd = 25, salaris = 3000.0, mobiel = 9922001), null, Medewerker (naam = Ace, leeftijd = 22, salaris = 2000.0, mobiel = 5924001), null, Medewerker (naam = Keith, leeftijd = 35, salaris = 4000,0, mobiel = 3924401)]

De nulls Eerste functie retourneert een Comparator dat houdt alles nulls aan het begin van de bestelvolgorde:

@Test openbare leegte whenNullsFirst_thenSortedByNameWithNullsFirst () {Comparator employeeNameComparator = Comparator.comparing (Werknemer :: getName); Comparator employeeNameComparator_nullFirst = Comparator.nullsFirst (employeeNameComparator); Arrays.sort (workersArrayWithNulls, employeeNameComparator_nullFirst); assertTrue (Arrays.equals (workersArrayWithNulls, gesorteerdEmployeesArray_WithNullsFirst)); }

Laten we eens kijken hoe de medewerkers matrixwaarden zijn gerangschikt volgens de sortering:

[null, null, Medewerker (naam = Ace, leeftijd = 22, salaris = 2000.0, mobiel = 5924001), Medewerker (naam = John, leeftijd = 25, salaris = 3000.0, mobiel = 9922001), Medewerker (naam = Keith, leeftijd = 35, salaris = 4000,0, mobiel = 3924401)]

5.2. Null Last overwegen

De nulls Laatste functie retourneert een Comparator dat houdt alles nulls aan het einde van de bestelprocedure:

@Test openbare leegte whenNullsLast_thenSortedByNameWithNullsLast () {Comparator employeeNameComparator = Comparator.comparing (Employee :: getName); Comparator employeeNameComparator_nullLast = Comparator.nullsLast (employeeNameComparator); Arrays.sort (workersArrayWithNulls, employeeNameComparator_nullLast); assertTrue (Arrays.equals (workersArrayWithNulls, gesorteerdEmployeesArray_WithNullsLast)); }

Laten we eens kijken hoe de medewerkers matrixwaarden zijn gerangschikt volgens de sortering:

[Medewerker (naam = Ace, leeftijd = 22, salaris = 2000,0, mobiel = 5924001), Medewerker (naam = John, leeftijd = 25, salaris = 3000,0, mobiel = 9922001), Medewerker (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401), null, null]

6. Met behulp van Comparator.thenComparing

De dan vergelijken functie kunt u lexicografische ordening van waarden instellen door meerdere sorteersleutels in een bepaalde volgorde in te voeren.

Laten we eens kijken naar een andere reeks Werknemer klasse:

someMoreEmployees = nieuwe werknemer [] {...};

Beschouw de volgende reeks elementen in de bovenstaande array:

[Medewerker (naam = Jake, leeftijd = 25, salaris = 3000.0, mobiel = 9922001), Medewerker (naam = Jake, leeftijd = 22, salaris = 2000.0, mobiel = 5924001), Medewerker (naam = Ace, leeftijd = 22, salaris = 3000.0, mobiel = 6423001), werknemer (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401)]

Laten we een reeks vergelijkingen schrijven als leeftijd gevolgd door de naam en zie de volgorde van deze array:

@Test openbaar ongeldig whenThenComparing_thenSortedByAgeName () {Comparator employee_Age_Name_Comparator = Comparator.comparing (Employee :: getAge) .thenComparing (Employee :: getName); Arrays.sort (someMoreEmployees, employee_Age_Name_Comparator); assertTrue (Arrays.equals (someMoreEmployees, gesorteerdEmployeesByAgeName)); }

Hier wordt de bestelling gedaan door leeftijd, en voor de waarden met hetzelfde leeftijd, bestellen wordt gedaan door naam. Laten we dit bekijken in de volgorde die we ontvangen na het sorteren:

[Medewerker (naam = Ace, leeftijd = 22, salaris = 3000.0, mobiel = 6423001), Medewerker (naam = Jake, leeftijd = 22, salaris = 2000.0, mobiel = 5924001), Medewerker (naam = Jake, leeftijd = 25, salaris = 3000.0, mobiel = 9922001), werknemer (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401)]

Laten we de andere versie van dan vergelijken dat is thenComparingInt, door de lexicografische volgorde te veranderen in naam gevolgd door leeftijd:

@Test openbaar ongeldig whenThenComparing_thenSortedByNameAge () {Comparator employee_Name_Age_Comparator = Comparator.comparing (Employee :: getName) .thenComparingInt (Employee :: getAge); Arrays.sort (someMoreEmployees, employee_Name_Age_Comparator); assertTrue (Arrays.equals (someMoreEmployees, gesorteerdEmployeesByNameAge)); }

Laten we eens kijken hoe de medewerkers matrixwaarden zijn gerangschikt volgens de sortering:

[Medewerker (naam = Ace, leeftijd = 22, salaris = 3000.0, mobiel = 6423001), Medewerker (naam = Jake, leeftijd = 22, salaris = 2000.0, mobiel = 5924001), Medewerker (naam = Jake, leeftijd = 25, salaris = 3000.0, mobiel = 9922001), werknemer (naam = Keith, leeftijd = 35, salaris = 4000.0, mobiel = 3924401)]

Evenzo zijn er functies thenComparingLong en thenComparingDouble voor gebruik lang en dubbele sorteersleutels.

7. Conclusie

Dit artikel is een gids voor verschillende functies die in Java 8 zijn geïntroduceerd voor Comparator koppel.

Zoals gewoonlijk is de broncode te vinden op Github.