Find forskellen mellem to lister i Java

1. Oversigt

At finde forskelle mellem samlinger af objekter af samme datatype er en almindelig programmeringsopgave. Forestil dig som et eksempel, at vi har en liste over studerende, der har ansøgt om eksamen, og en anden liste over studerende, der har bestået den. Forskellen mellem disse to lister ville give os de studerende, der ikke bestod eksamen.

I Java, er der ingen eksplicit måde at finde forskelle mellem to lister i Liste API, selvom der er nogle hjælpemetoder, der kommer tæt på.

I denne hurtige vejledning vi ser på, hvordan man finder forskellene mellem de to lister. Vi prøver et par forskellige tilgange, herunder almindelig Java (med og uden Strømme) og brug af tredjepartsbiblioteker som f.eks Guava og Apache Commons samlinger.

2. Testopsætning

Lad os starte med at definere to lister, som vi bruger til at teste vores eksempler:

offentlig klasse FindDifferencesBetweenListsUnitTest {private static final List listOne = Arrays.asList ("Jack", "Tom", "Sam", "John", "James", "Jack"); privat statisk endelig List listTwo = Arrays.asList ("Jack", "Daniel", "Sam", "Alan", "James", "George"); }

3. Brug af Java Liste API

Vi kan oprette en kopi af den ene liste, og fjern derefter alle de elementer, der er fælles med den anden, bruger Liste metode Fjern alt():

Listeforskelle = ny ArrayList (listOne); difference.removeAll (listTwo); assertEquals (2, difference.size ()); hævder, at (forskelle). indeholder nøjagtigt ("Tom", "John");

Lad os vende dette for at finde forskellene omvendt:

Listeforskelle = ny ArrayList (listTwo); difference.removeAll (listOne); assertEquals (3, difference.size ()); hævder, at (forskelle). indeholder nøjagtigt ("Daniel", "Alan", "George");

Vi skal også bemærke, at hvis vi vil finde de fælles elementer mellem de to lister, Liste indeholder også en bevar alle metode.

4. Brug af Streams API

En Java Strøm kan bruges til at udføre sekventielle operationer på data fra samlinger, som inkluderer filtrering af forskelle mellem lister:

Listeforskelle = listOne.stream () .filter (element ->! ListTwo.contains (element)) .collect (Collectors.toList ()); assertEquals (2, difference.size ()); hævder, at (forskelle). indeholder nøjagtigt ("Tom", "John");

Som i vores første eksempel kan vi skifte rækkefølgen af ​​lister for at finde de forskellige elementer fra den anden liste:

Listeforskelle = listTwo.stream () .filter (element ->! ListOne.contains (element)) .collect (Collectors.toList ()); assertEquals (3, difference.size ()); hævder, at (forskelle) .indholder nøjagtigt ("Daniel", "Alan", "George");

Vi skal bemærke, at den gentagne kaldelse af Liste.indeholder() kan være en dyr handling for større lister.

5. Brug Tredjepartsbiblioteker

5.1. Brug af Google Guava

Guava indeholder en praktisk Sæt.forskel metode, men for at bruge det skal vi først konvertere vores Liste til en Sæt:

Listeforskelle = ny ArrayList (Sets.difference (Sets.newHashSet (listOne), Sets.newHashSet (listTwo))); assertEquals (2, difference.size ()); assertThat (forskelle) .containsExactlyInAnyOrder ("Tom", "John");

Vi skal bemærke, at konvertering af Liste til en Sæt vil medføre, at det duplikeres og omordnes.

5.2. Brug af Apache Commons-samlinger

Det CollectionUtils klasse fra Apache Commons samlinger indeholder en Fjern alt metode.

Denne metode gør samme som Liste.Fjern alt, samtidig med at der oprettes en ny samling til resultatet:

Listeforskelle = ny ArrayList ((CollectionUtils.removeAll (listOne, listTwo))); assertEquals (2, difference.size ()); hævder, at (forskelle). indeholder nøjagtigt ("Tom", "John");

6. Håndtering af duplikatværdier

Lad os nu se på at finde forskelle, når to lister indeholder duplikerede værdier.

For at opnå dette, vi er nødt til at fjerne duplikatelementerne fra den første liste, nøjagtigt så mange gange som de er indeholdt i den anden liste.

I vores eksempel er værdien “Jack” vises to gange i den første liste og kun en gang på den anden liste:

Listeforskelle = ny ArrayList (listOne); listTwo.forEach (forskelle :: fjern); hævder, at (forskelle). indeholder nøjagtigt ("Tom", "John", "Jack");

Vi kan også opnå dette ved hjælp af trække fra metode fra Apache Commons samlinger:

Listeforskelle = ny ArrayList (CollectionUtils.subtract (listOne, listTwo)); assertEquals (3, difference.size ()); hævder, at (forskelle). indeholder nøjagtigt ("Tom", "John", "Jack");

7. Konklusion

I denne artikel vi undersøgte et par måder at finde forskelle på listerne.

I eksemplerne dækkede vi en grundlæggende Java-løsning, en løsning ved hjælp af Strømme API og med tredjepartsbiblioteker som Google Guava og Apache Commons samlinger.

Vi så også, hvordan man håndterer duplikerede værdier.

Som altid er den komplette kildekode tilgængelig på GitHub.