Encontrar las diferencias entre dos listas en Java
En esta entrada vamos a ver como podemos encontrar las diferencias entre dos listas en Java. Para ello vamos a ver diferentes aproximaciones desde utilizar el API de Java con ArrayList hasta hacer uso de Streams en Java.
En este artículo y en sus ejemplos veremos las diferencias entre listA y listB, es decir, encontraremos los elementos que listB tiene en listA y se mantienen los elementos de listA. Se mantienen los elementos únicos de listA.
Si quieres ir directamente al ejemplo de código pulsa aquí.
Uso de API de ArrayList para encontrar diferencias entre dos listas en Java
El método más rápido para poder encontrar las diferencias entre dos listas en Java es hacer uso del método removeAll(lista).
Vamos a ver un test:
@Test public void given_two_list_when_get_difference_with_api_java_then_get_difference() { List listA = Arrays.asList("Amarillo", "Rojo", "Azul", "Verde", "Gris"); List listB = Arrays.asList("Amarillo", "Rojo", "Violeta", "Marrón", "Negro"); final List expectedList = Arrays.asList("Azul", "Verde", "Gris"); List<String> differences = new ArrayList<>(listA); differences.removeAll(listB); assertEquals(3, differences.size()); assertEquals(differences, expectedList); }
Encontrar elementos diferentes en listas en Java con el API de Stream
Con el API de Stream podemos encontrar las diferencias entre dos listas haciendo uso de filter(), con lo que podemos utilizar una condición para encontrar las diferencias.
@Test public void given_two_list_when_get_difference_with_api_stream_then_get_difference() { List listA = Arrays.asList("Amarillo", "Rojo", "Azul", "Verde", "Gris"); List listB = Arrays.asList("Amarillo", "Rojo", "Violeta", "Marrón", "Negro"); final List expectedList = Arrays.asList("Azul", "Verde", "Gris"); List<String> differences = (List<String>) listA.stream() .filter(element -> !listB.contains(element)) .collect(Collectors.toList()); assertEquals(3, differences.size()); assertEquals(differences, expectedList); }
Uso de bucle For para encontrar elementos diferentes entre listas en Java
El uso de un bucle for para encontrar los elementos diferentes entre listas en Java es una de las maneras más clásicas.
@Test public void given_two_list_when_get_difference_with_for_then_get_difference() { List listA = Arrays.asList("Amarillo", "Rojo", "Azul", "Verde", "Gris"); List listB = Arrays.asList("Amarillo", "Rojo", "Violeta", "Marrón", "Negro"); final List expectedList = Arrays.asList("Azul", "Verde", "Gris"); List<String> differences = new ArrayList<>(); for (Object elementA: listA){ boolean equals = false; for (Object elementB: listB) { if (elementA.equals(elementB)) { equals = true; } } if (!equals) { differences.add((String) elementA); } } assertEquals(3, differences.size()); assertEquals(differences, expectedList); }
Bucle While
Otra de las formas convencionales de obtener las diferencias entre dos listas manteniendo los elementos únicos de la primera lista.
@Test public void given_two_list_when_get_difference_with_while_then_get_difference() { List listA = Arrays.asList("Amarillo", "Rojo", "Azul", "Verde", "Gris"); List listB = Arrays.asList("Amarillo", "Rojo", "Violeta", "Marrón", "Negro"); final List expectedList = Arrays.asList("Azul", "Verde", "Gris"); List<String> differences = new ArrayList<>(); int i = 0; int j = 0; while (listA.size() > i){ boolean equals = false; while (!equals && listB.size() > j) { if (listA.get(i).equals(listB.get(j))) { equals = true; } j++; } if (!equals) { differences.add((String) listA.get(i)); } i++; } assertEquals(3, differences.size()); assertEquals(differences, expectedList); }
Obviamente por el boilerplate generado tanto con un bucle for como while es mejor hacer uso de otras aproximaciones.
Librería Guava de Google para encontrar diferencias en Java
La librería de Google Guava nos permite, también encontrar las diferencias entre listas. Lo primero es añadir la dependencia:
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.0</version> </dependency>
Para obtener las diferencias entre dos listas con Guava podemos hacer uso del método Sets.difference. Este método nos obliga a trabajar con Set en lugar de con List.
@Test public void given_two_list_when_get_difference_with_guava_then_get_difference() { List listA = Arrays.asList("Amarillo", "Rojo", "Azul", "Verde", "Gris"); List listB = Arrays.asList("Amarillo", "Rojo", "Violeta", "Marrón", "Negro"); final List expectedList = Arrays.asList("Azul", "Verde", "Gris"); List<String> differences = new ArrayList<>(Sets.difference(Sets.newHashSet(listA), Sets.newHashSet(listB))); assertEquals(3, differences.size()); assertTrue(differences.size() == expectedList.size() && differences.containsAll(expectedList) && expectedList.containsAll(differences)); }
Uso de Apache Commons Collections
Para hacer uso de Apache Commons lo primero es añadir su dependencia:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.4</version> </dependency>
La clase CollectionUtils dentro de la librería de Apache Commons contiene el método removeAll, que tiene el mismo funcionamiento que el removeAll de una lista:
@Test public void given_two_list_when_get_difference_with_apache_commons_then_get_difference() { List listA = Arrays.asList("Amarillo", "Rojo", "Azul", "Verde", "Gris"); List listB = Arrays.asList("Amarillo", "Rojo", "Violeta", "Marrón", "Negro"); final List expectedList = Arrays.asList("Azul", "Verde", "Gris"); List<String> differences = new ArrayList<>(CollectionUtils.removeAll(listA, listB)); assertEquals(3, differences.size()); assertTrue(differences.size() == expectedList.size() && differences.containsAll(expectedList) && expectedList.containsAll(differences)); }
Conclusión
En este artículo sobre encontrar las diferencias entre dos listas en Java, hemos visto las diferentes aproximaciones para obtener los elementos únicos de una lista en comparación con otra. Hemos visto diferentes aproximaciones, desde las más clásicas que funcionarían en cualquier lenguaje de programación, hasta las más efectivas en términos de líneas de código.
Si quieres ver el ejemplo que hemos utilizado, lo puedes ver aquí.
Si necesitas más información puedes escribirnos un comentario o un correo electrónico a refactorizando.web@gmail.com o también nos puedes contactar por nuestras redes sociales Facebook o twitter y te ayudaremos encantados!