First, naming a class People
is not natural, a better name would be Person
.
As, for solving your problem, you can override equals
and hashcode
for height
only like this:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return height == person.height;
}
@Override
public int hashCode() {
return height;
}
The above assumes height is an int
field. if instead, it's Integer
, then you'll need to implement it like so:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return height != null ? height.equals(person.height) : person1.height == null;
}
@Override
public int hashCode() {
return height != null ? height.hashCode() : 0;
}
Now, you can do:
Set<People> uniquePeople =
myList.stream()
.filter(Objects::nonNull)
.collect(Collectors.toSet());
or for what ever reason you don't want to override equals
and hashcode
you can do it with the toMap
collector.
Set<Person> values = new HashSet<>(myList.stream()
.collect(Collectors.toMap(Person::getHeight, Function.identity(),
(left, right) -> left))
.values());
deciphering the above code snippet:
myList.stream()
.collect(Collectors.toMap(Person::getHeight, Function.identity(),
(left, right) -> left))
.values()
This creates a stream from myList
collecting it to a map implementation, where Person::getHeight
is a function extracting the person height for the map keys, Function.identity()
is a function extracting a person object for the map values, (left, right) -> left)
is known as the merge function meaning if two given people have the same key (height) we return the first person (left
). Conversely, (left, right) -> right
will return the last person in the case of key conflict.
Lastly, we pass the result of this processing to the HashSet
constructor to create a Set<Person>
.