Java: encontrar elementos duplicados en una secuencia

    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 鈥嬧媏n 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.

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *