una repetidos registros quitar para objetos numeros matriz lista eliminar elementos duplicados datos arreglo array algoritmo java java-8 java-stream

registros - numeros repetidos en una matriz java



Ignorar duplicados al producir mapas usando flujos (5)

Map<String, String> phoneBook=people.stream() .collect(toMap(Person::getName, Person::getAddress));

Recibo una excepción de clave duplicada cuando ocurren duplicados.

¿Es posible ignorar agregar los valores al mapa cuando ocurren los duplicados?

Cuando hay duplicado, simplemente debe continuar ignorando esa clave duplicada.


Asumiendo que tienes personas es una lista de objetos

Map<String, String> phoneBook=people.stream() .collect(toMap(Person::getName, Person::getAddress));

Ahora necesitas dos pasos:

1)

people =removeDuplicate(people);

2)

Map<String, String> phoneBook=people.stream() .collect(toMap(Person::getName, Person::getAddress));

Aquí hay un método para eliminar duplicados

public static List removeDuplicate(Collection<Person> list) { if(list ==null || list.isEmpty()){ return null; } Object removedDuplicateList = list.stream() .distinct() .collect(Collectors.toList()); return (List) removedDuplicateList; }

Agregar un ejemplo completo aquí

package com.example.khan.vaquar; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class RemovedDuplicate { public static void main(String[] args) { Person vaquar = new Person(1, "Vaquar", "Khan"); Person zidan = new Person(2, "Zidan", "Khan"); Person zerina = new Person(3, "Zerina", "Khan"); // Add some random persons Collection<Person> duplicateList = Arrays.asList(vaquar, zidan, zerina, vaquar, zidan, vaquar); // System.out.println("Before removed duplicate list" + duplicateList); // Collection<Person> nonDuplicateList = removeDuplicate(duplicateList); // System.out.println(""); System.out.println("After removed duplicate list" + nonDuplicateList); ; // 1) solution Working code Map<Object, Object> k = nonDuplicateList.stream().distinct() .collect(Collectors.toMap(s1 -> s1.getId(), s1 -> s1)); System.out.println(""); System.out.println("Result 1 using method_______________________________________________"); System.out.println("k" + k); System.out.println("_____________________________________________________________________"); // 2) solution using inline distinct() Map<Object, Object> k1 = duplicateList.stream().distinct() .collect(Collectors.toMap(s1 -> s1.getId(), s1 -> s1)); System.out.println(""); System.out.println("Result 2 using inline_______________________________________________"); System.out.println("k1" + k1); System.out.println("_____________________________________________________________________"); //breacking code System.out.println(""); System.out.println("Throwing exception _______________________________________________"); Map<Object, Object> k2 = duplicateList.stream() .collect(Collectors.toMap(s1 -> s1.getId(), s1 -> s1)); System.out.println(""); System.out.println("k2" + k2); System.out.println("_____________________________________________________________________"); } public static List removeDuplicate(Collection<Person> list) { if (list == null || list.isEmpty()) { return null; } Object removedDuplicateList = list.stream().distinct().collect(Collectors.toList()); return (List) removedDuplicateList; } } // Model class class Person { public Person(Integer id, String fname, String lname) { super(); this.id = id; this.fname = fname; this.lname = lname; } private Integer id; private String fname; private String lname; // Getters and Setters public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getFname() { return fname; } public void setFname(String fname) { this.fname = fname; } public String getLname() { return lname; } public void setLname(String lname) { this.lname = lname; } @Override public String toString() { return "Person [id=" + id + ", fname=" + fname + ", lname=" + lname + "]"; } }

Resultados:

Before removed duplicate list[Person [id=1, fname=Vaquar, lname=Khan], Person [id=2, fname=Zidan, lname=Khan], Person [id=3, fname=Zerina, lname=Khan], Person [id=1, fname=Vaquar, lname=Khan], Person [id=2, fname=Zidan, lname=Khan], Person [id=1, fname=Vaquar, lname=Khan]] After removed duplicate list[Person [id=1, fname=Vaquar, lname=Khan], Person [id=2, fname=Zidan, lname=Khan], Person [id=3, fname=Zerina, lname=Khan]] Result 1 using method_______________________________________________ k{1=Person [id=1, fname=Vaquar, lname=Khan], 2=Person [id=2, fname=Zidan, lname=Khan], 3=Person [id=3, fname=Zerina, lname=Khan]} _____________________________________________________________________ Result 2 using inline_______________________________________________ k1{1=Person [id=1, fname=Vaquar, lname=Khan], 2=Person [id=2, fname=Zidan, lname=Khan], 3=Person [id=3, fname=Zerina, lname=Khan]} _____________________________________________________________________ Throwing exception _______________________________________________ Exception in thread "main" java.lang.IllegalStateException: Duplicate key Person [id=1, fname=Vaquar, lname=Khan] at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133) at java.util.HashMap.merge(HashMap.java:1253) at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320) at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169) at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at com.example.khan.vaquar.RemovedDuplicate.main(RemovedDuplicate.java:48)


Como se dijo en JavaDocs :

Si las claves asignadas contienen duplicados (de acuerdo con Object.equals(Object) ), se IllegalStateException una IllegalStateException cuando se realiza la operación de recopilación. Si las teclas asignadas pueden tener duplicados, use toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction) lugar.

Por lo tanto, debe usar toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction) lugar. Solo proporcione la función de fusión, que determinará cuál de los duplicados necesita para poner en el mapa. Por ejemplo, si no le importa cuál, simplemente llame

Map<String, String> phoneBook = people.stream() .collect(Collectors.toMap(Person::getName, Person::getAddress, (a1, a2) -> a1));


Esto es posible utilizando el parámetro mergeFunction de Collectors.toMap(keyMapper, valueMapper, mergeFunction) :

Map<String, String> phoneBook = people.stream() .collect(Collectors.toMap( Person::getName, Person::getAddress, (address1, address2) -> { System.out.println("duplicate key found!"); return address1; } ));

mergeFunction es una función que opera en dos valores asociados con la misma clave. adress1 corresponde a la primera dirección que se encontró al recopilar elementos y adress2 corresponde a la segunda dirección encontrada: esta lambda simplemente le dice que mantenga la primera dirección e ignora la segunda.


La respuesta @alaster me ayudó mucho, pero me gustaría agregar una información significativa si alguien está tratando de agrupar la información.

Si tiene, por ejemplo, dos Orders con el mismo code pero diferente quantity de productos para cada uno, y su deseo es sumar las cantidades, puede hacer:

List<Order> listQuantidade = new ArrayList<>(); listOrders.add(new Order("COD_1", 1L)); listOrders.add(new Order("COD_1", 5L)); listOrders.add(new Order("COD_1", 3L)); listOrders.add(new Order("COD_2", 3L)); listOrders.add(new Order("COD_3", 4L)); listOrders.collect(Collectors.toMap(Order::getCode, o -> o.getQuantity(), (o1, o2) -> o1 + o2));

Resultado:

{COD_3=4, COD_2=3, COD_1=9}


Me encontré con un problema de este tipo al agrupar objetos, siempre los resolví de una manera simple: realice un filtro personalizado usando java.util.Set para eliminar objetos duplicados con cualquier atributo de su elección como se muestra a continuación

Set<String> uniqueNames = new HashSet<>(); Map<String, String> phoneBook = people .stream() .filter(person -> person != null && !uniqueNames.add(person.getName())) .collect(toMap(Person::getName, Person::getAddress));

Espero que esto ayude a cualquiera que tenga el mismo problema.