I have a list of objects of type Person and I want to get rid of elements that have the same name, using streams. I have found on the internet a suggestion to use a Wrapper class and my code looks like this so far:
List<Person> people = Arrays.asList(new Person("Kowalski"), new Person("Nowak"), new Person("Big"), new Person("Kowalski")); List<Person> distPeople = people.stream() .map(Wrapper::new) .distinct() .map(Wrapper::unwrap) .collect(Collectors.toList()); In documentation it is said that distinct()
Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.
Implementation of Wrapper that doesn't work (I get the same stream with two Kowalski):
public class Wrapper { private final Person person; Wrapper(Person p) { person = p; } public Person unwrap() { return person; } public boolean equals(Object other) { if(other instanceof Wrapper) return ((Wrapper) other).person.getName().equals(person.getName()); else return false; } } Implementation of Wrapper class works after adding this:
@Override public int hashCode() { return person.getName().hashCode(); } Can someone explain why after overriding hashCode() in the Wrapper class distinct() works?
distinct()likely uses aHashSetfor best performance. You should always implementhashCode()when you implementequals().equalsandhashCodeshould always be overridden together so as to yield consistent results. Otherwise you are violating the contract ofObject.