Java: encontrar elementos duplicados en una secuencia

J

Introducción

Introducida en Java 8, la API Stream se usa comúnmente para filtrar, mapear e iterar sobre elementos. Cuando se trabaja con flujos, una de las tareas habituales es encontrar elementos duplicados.

En este tutorial, cubriremos varias formas de encontrar elementos duplicados en una secuencia de Java.

Collectors.toSet ()

La forma más sencilla de encontrar elementos duplicados es agregando los elementos en un Set. Sets no pueden contener valores duplicados, y el Set.add() el método devuelve un boolean valor que es el resultado de la operación. Si no se agrega un elemento, false se devuelve y viceversa.

Hagamos un Stream de Strings con algunos valores duplicados. Estos valores se comprueban mediante el equals() , así que asegúrese de tener uno implementado adecuadamente para las clases personalizadas:

Stream<String> stream = Stream.of("john", "doe", "doe", "tom", "john");

Ahora, hagamos un Set para almacenar los elementos filtrados. Usaremos el filter() método para filtrar valores duplicados y devolverlos:

Set<String> items = new HashSet<>();

stream.filter(n -> !items.add(n))
        .collect(Collectors.toSet())
        .forEach(System.out::println);

Aquí, intentamos add() cada elemento al Set. Si no se agrega, debido a que está duplicado, recopilamos ese valor y lo imprimimos:

john
doe

Collectors.toMap ()

Alternativamente, también puede contar las ocurrencias de elementos duplicados y mantener esa información en un mapa que contiene los elementos duplicados como claves y su frecuencia como valores.

Vamos a crear un List de Integer tipo:

List<Integer> list = Arrays.asList(9, 2, 2, 7, 6, 6, 5, 7);

Luego, recopilemos los elementos en un Map y contar sus ocurrencias:

Map<Integer, Integer> map = list.stream()
        .collect(Collectors.toMap(Function.identity(), value -> 1, Integer::sum));
        
System.out.println(map);

No hemos eliminado ningún elemento, solo contamos sus apariciones y las almacenamos en un Map:

{2=2, 5=1, 6=2, 7=2, 9=1}

Collectors.groupingBy (Function.identity (), Collectors.counting ()) con Collectors.toList ()

los Collectors.groupingBy() El método se utiliza para agrupar elementos, según alguna propiedad, y devolverlos como un Map ejemplo.

En nuestro caso, el método recibe dos parámetros: Function.identity(), que siempre devuelve sus argumentos de entrada y Collectors.counting(), que cuenta los elementos pasados ​​en la secuencia.

Entonces, usaremos el groupingBy() método para crear un mapa de la frecuencia de estos elementos. Después de eso, podemos simplemente filter() el flujo de elementos que tienen una frecuencia superior a 1:

list.stream()
        // Creates a map {4:1, 5:2, 7:2, 8:2, 9:1}
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
        .entrySet()
        // Convert back to stream to filter
        .stream()
        .filter(element -> element.getValue() > 1)
        // Collect elements to List and print out the values
        .collect(Collectors.toList())
        .forEach(System.out::println);

Esto resulta en:

5=2
7=2
8=2

Si desea extraer solo los elementos duplicados, sin su frecuencia, puede agregar una map() en el proceso. Después de filtrar y antes de recopilar una lista, obtendremos solo las claves:

.map(Map.Entry::getKey)

Colecciones.frecuencia ()

Collections.frequency() es otro método que proviene de la clase Colecciones de Java que cuenta las apariciones de un elemento especificado en el flujo de entrada atravesando cada elemento. Se necesitan dos parámetros, la colección y el elemento cuya frecuencia se va a determinar.

Ahora bien filter() la secuencia para cada elemento que tiene un frequency() mayor que 1:

list.stream()
        .filter(i -> Collections.frequency(list, i) > 1)
        //Collect elements to a Set and print out the values 
        .collect(Collectors.toSet())
        .forEach(System.out::println);

Aquí, podemos recolectar a un Set oa un List. Si recopilamos en una lista, tendrá todos los elementos duplicados, por lo que algunos pueden repetirse. Si recopilamos en un conjunto, tendrá elementos duplicados únicos.

Esto resulta en:

5
7
8

Stream.distinct ()

los distinct() El método es un método con estado (mantiene el estado de los elementos anteriores en mente) y compara elementos usando equals() método. Si son distintos / únicos, se devuelven, que podemos completar en otra lista.

Hagamos una lista con algunos valores duplicados y extraigamos los valores distintos:

List<String> list = new ArrayList(Arrays.asList("A", "B", "C", "D", "A", "B", "C", "A", "F", "C"));

List<String> distinctElementList = list.stream()
        .distinct()
        .collect(Collectors.toList());

Ahora, todos los valores no distintos tienen más de una ocurrencia. Si eliminamos los valores distintos, nos quedarán elementos duplicados:

for (String distinctElement : distinctElementList) {
    list.remove(distinctElement);
}

Ahora, imprimamos los resultados:

list.forEach(System.out::print)

Estos son los elementos duplicados, con sus respectivas ocurrencias:

ABCAC

Si también desea examinarlos, y solo mostrar una aparición de cada elemento duplicado (en lugar de todos ellos por separado), puede ejecutarlos a través del distinct() método de nuevo:

list.stream()
        .distinct()
        .collect(Collectors.toList())
        .forEach(System.out::print);

Esto resulta en:

ABC

Conclusión

En este artículo, hemos repasado algunos enfoques para encontrar elementos duplicados en una secuencia de Java.

Hemos cubierto el Stream.distinct() método de la API Stream, el Collectors.toSet(), Collectors.toMap() y Collectors.groupingBy() métodos de Java Collectors, así como Collections.frequency() método del marco de las colecciones.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad