JAVA : How to remove duplicates from list using stream

Viewed 202

I want to remove duplicates from a list based on a property(mail) of the items in the list.
I did this :

acteurs = acteurs.stream().distinct().collect(Collectors.toList());

The equals method of Acteur

@Override
public boolean equals(Object o) {
    if (this.getMail().equals(((Acteur)o).getMail())) {
        return true;
    }
    if (this == o) {
        return true;
    }
    if (o == null || getClass() != o.getClass()) {
        return false;
    }
    Acteur acteur = (Acteur) o;
    if(acteur.id == null || id == null) {
        return false;
    }
    return Objects.equals(id, acteur.id);
}

The equals method should be called during the instruction

acteurs = acteurs.stream().distinct().collect(Collectors.toList());

But it isn't.
Where am I wrong?

UPDATE :
My solution :

List<Acteur> dto3s =acteurs.stream()
            .collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Acteur:: getMail))),
                ArrayList::new));
3 Answers

You broke equals/hashCode contract.

You need to implement hashCode according to requirements.

you can use the following solution, where you create a map by the distinct key mail and get the map's values

acteurs.stream().collect(Collectors.toMap(a -> a.getMail(), Function.identity(), (a1, a2) -> a1)).values();

the third arg (a1, a2) -> a1 means that whenever it get a conflicts i.e need to add to the map an entry (key,value) with the same key it will use the map's current value, i.e no-op

keep in mind, this will only compare by mail property, if you want to compare by a more complex way using the map logic, you might need to implement hash() and equals() properly

Your equals method seems not correct because you need to "return false" if the "if condition" is not fulfilled

Related