Map<String, String> phoneBook=people.stream()
.collect(toMap(Person::getName, Person::getAddress));
Je reçois une exception de clé en double lorsque des doublons se produisent.
Est-il possible d'ignorer d'ajouter les valeurs à mapper lorsque les doublons se produisent?
Quand il y a des doublons, il devrait simplement continuer en ignorant cette clé en double.
Ceci est possible en utilisant le paramètre 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
est une fonction qui opère sur deux valeurs associées à la même clé. adress1
correspond à la première adresse rencontrée lors de la collecte d'éléments et adress2
correspond à la deuxième adresse rencontrée: ce lambda indique simplement de conserver la première adresse et ignore la deuxième.
Comme indiqué dans JavaDocs :
Si les clés mappées contiennent des doublons (selon
Object.equals(Object)
), uneIllegalStateException
est renvoyée lorsque le fichier l'opération de collecte est effectuée. Si les clés mappées peuvent avoir les doublons, utiliseztoMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)
à la place.
Vous devriez donc utiliser toMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)
à la place. Il suffit de fournir la fonction de fusion, qui déterminera lequel des doublons doit être mis en carte. Par exemple, si vous ne vous souciez pas de laquelle, appelez simplement
Map<String, String> phoneBook = people.stream()
.collect(Collectors.toMap(Person::getName, Person::getAddress, (p1, p2) -> p1));
J'ai rencontré un tel problème lors du regroupement d'objet, je les ai toujours résolus de manière simple: effectuez un filtre personnalisé à l'aide d'un fichier Java.util.Set pour supprimer les objets en double avec l'attribut de votre choix (voir ci-dessous).
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));
J'espère que cela aide tous ceux qui ont le même problème!
La réponse @alaster m'aide beaucoup, mais j'aimerais ajouter une information utile si quelqu'un essaie de la regrouper.
Si vous avez, par exemple, deux Orders
avec le même code
mais différent quantity
de produits pour chaque produit et si vous désirez somme les quantités, vous pouvez faire
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));
Résultat:
{COD_3=4, COD_2=3, COD_1=9}
En supposant que vous avez des gens est la liste d'objet
Map<String, String> phoneBook=people.stream()
.collect(toMap(Person::getName, Person::getAddress));
Maintenant, vous avez besoin de deux étapes:
1)
people =removeDuplicate(people);
2)
Map<String, String> phoneBook=people.stream()
.collect(toMap(Person::getName, Person::getAddress));
Voici la méthode pour supprimer les doublons
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;
}
Ajout de l'exemple complet ici
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 + "]";
}
}
Résultats :
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)