De verschillen tussen twee lijsten in Java vinden

1. Overzicht

Het vinden van verschillen tussen verzamelingen objecten van hetzelfde gegevenstype is een gebruikelijke programmeertaak. Stel je voor dat we een lijst hebben met studenten die zich hebben aangemeld voor een examen en een andere lijst met studenten die ervoor geslaagd zijn. Het verschil tussen die twee lijsten zou ons de studenten opleveren die het examen niet hebben gehaald.

In Java, is er geen expliciete manier om verschillen te vinden tussen twee lijsten in het Lijst API, hoewel er enkele hulpmethoden zijn die in de buurt komen.

In deze korte tutorial, we zullen kijken hoe we de verschillen tussen de twee lijsten kunnen vinden. We zullen een paar verschillende benaderingen proberen, waaronder gewoon Java (met en zonder Streams) en het gebruik van bibliotheken van derden, zoals Guave en de Apache Commons-collecties.

2. Testopstelling

Laten we beginnen met het definiëren van twee lijsten, die we zullen gebruiken om onze voorbeelden te testen:

openbare klasse FindDifferencesBetweenListsUnitTest {privé statische laatste lijst listOne = Arrays.asList ("Jack", "Tom", "Sam", "John", "James", "Jack"); privé statische definitieve lijst listTwo = Arrays.asList ("Jack", "Daniel", "Sam", "Alan", "James", "George"); }

3. Met behulp van de Java Lijst API

We kunnen een kopie van de ene lijst en verwijder vervolgens alle elementen die gemeenschappelijk zijn met de andere, de ... gebruiken Lijst methode Verwijder alles():

Lijstverschillen = nieuwe ArrayList (listOne); verschillen.removeAll (listTwo); assertEquals (2, verschillen.size ()); assertThat (verschillen) .containsExactly ("Tom", "John");

Laten we dit omkeren om de verschillen andersom te vinden:

Lijstverschillen = nieuwe ArrayList (listTwo); verschillen.removeAll (listOne); assertEquals (3, verschillen.size ()); assertThat (verschillen) .containsExactly ("Daniel", "Alan", "George");

We moeten ook opmerken dat als we de gemeenschappelijke elementen tussen de twee lijsten willen vinden, Lijst bevat ook een keepAll methode.

4. Met behulp van de Streams API

Een Java Stroom kan worden gebruikt voor het uitvoeren van opeenvolgende bewerkingen op gegevens uit verzamelingen, waaronder verschillen tussen lijsten filteren:

Lijstverschillen = listOne.stream () .filter (element ->! ListTwo.contains (element)) .collect (Collectors.toList ()); assertEquals (2, verschillen.size ()); assertThat (verschillen) .containsExactly ("Tom", "John");

Net als in ons eerste voorbeeld, kunnen we de volgorde van lijsten wijzigen om de verschillende elementen uit de tweede lijst te vinden:

Lijstverschillen = listTwo.stream () .filter (element ->! ListOne.contains (element)) .collect (Collectors.toList ()); assertEquals (3, verschillen.size ()); assertThat (verschillen) .containsExactly ("Daniel", "Alan", "George");

We moeten opmerken dat de herhaalde roeping van Lijst.bevat () kan een kostbare operatie zijn voor grotere lijsten.

5. Met behulp van Bibliotheken van derden

5.1. Met Google Guava

Guave bevat een handige Sets.verschil methode, maar om het te gebruiken moeten we eerst onze Lijst naar een Set:

Lijstverschillen = nieuwe ArrayList (Sets.difference (Sets.newHashSet (listOne), Sets.newHashSet (listTwo))); assertEquals (2, verschillen.size ()); assertThat (verschillen) .containsExactlyInAnyOrder ("Tom", "John");

We moeten opmerken dat het converteren van de Lijst naar een Set zal het effect hebben dat het ontdubbeld en opnieuw geordend wordt.

5.2. Apache Commons-verzamelingen gebruiken

De CollectionUtils klas van Apache Commons-collecties bevat een Verwijder alles methode.

Deze methode doet het hetzelfde als Lijst.Verwijder alles, terwijl er ook een nieuwe collectie voor het resultaat wordt gemaakt:

Lijstverschillen = nieuwe ArrayList ((CollectionUtils.removeAll (listOne, listTwo))); assertEquals (2, verschillen.size ()); assertThat (verschillen) .containsExactly ("Tom", "John");

6. Omgaan met dubbele waarden

Laten we nu kijken naar het vinden van verschillen wanneer twee lijsten dubbele waarden bevatten.

Om dit te behalen, we moeten de dubbele elementen uit de eerste lijst verwijderen, net zo vaak als ze in de tweede lijst voorkomen.

In ons voorbeeld is de waarde "Jack" komt twee keer voor in de eerste lijst en slechts één keer in de tweede lijst:

Lijstverschillen = nieuwe ArrayList (listOne); listTwo.forEach (verschillen :: verwijderen); assertThat (verschillen) .containsExactly ("Tom", "John", "Jack");

We kunnen dit ook bereiken met de aftrekken methode van Apache Commons-collecties:

Lijstverschillen = nieuwe ArrayList (CollectionUtils.subtract (listOne, listTwo)); assertEquals (3, verschillen.size ()); assertThat (verschillen) .containsExactly ("Tom", "John", "Jack");

7. Conclusie

In dit artikel, we hebben een aantal manieren onderzocht om verschillen tussen lijsten te vinden.

In de voorbeelden hebben we een eenvoudige Java-oplossing behandeld, een oplossing met behulp van de Streams API, en met bibliotheken van derden, zoals Google Guava en Apache Commons-collecties.

We hebben ook gezien hoe om te gaan met dubbele waarden.

Zoals altijd is de volledige broncode beschikbaar op GitHub.