How can I get the distinct element from list based on multiple condition using java 8 stream ?
For example - Let's assume an object Person
:
class Person {
Integer id;
String name;
}
I want to have a list with unique combination of id
and name
.
There can be multiple records with same id and name in list
You can create your own distinct method for example :
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
So you can use it with filter :
List<Person> persons = listPersons.stream()
//@Holger suggest
.filter(distinctByKey(pr -> Arrays.asList(pr.getId(), pr.getName())))
.collect(toList());
Take a look at this :
If your list person is :
List<Person> listPersons = Arrays.asList(
new Person(1, "person1"),
new Person(1, "person5"),
new Person(2, "person2"),
new Person(1, "person1"),
new Person(1, "person2"),
new Person(1, "person1"),
new Person(3, "person3")
);
Outputs
Person{id=1, name=person1}
Person{id=1, name=person5}
Person{id=2, name=person2}
Person{id=1, name=person2}
Person{id=3, name=person3}
Override hashCode()
and equals()
methods for your class, then you can do something like this:
Set<Person> result = persons.stream().collect(Collectors.toSet());
Set is a data structure that does not allow duplicates so this way you'll only have unique elements.
Here is a solution: https://ideone.com/e.js/G7T2rH
Below are the steps to get the solution.
You need to implement equals and hashcode in class Person for equality check. If you have overridden these methods in your class, whenever there is an equality check, the methods implemented in Person will be called and will always return the unique result.
class Person {
Integer id;
String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person p = (Person) o;
return id == p.id && Objects.equals(name, p.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
Use any of the below methods for getting distinct Person value:
a). Use Set because Set contains only unique values. It's an unordered collection.
Set<Person> set=new HashSet<Person>();
for(Person c:list){
set.add(c);
}
b). Using Java8 Stream API:
List<Person> unique = list.stream().collect(collectingAndThen(toCollection(() -> new TreeSet<>(comparingInt(Person::getId))),
ArrayList::new));
c). If ordered collection is required:
LinkedHashSet<Person> lset=new LinkedHashSet<Person>();
for(Personc:list){
lset.add(c);
}
d) Java 8 Stream API method:
List<Person> ll= list.stream().distinct().collect(Collectors.toList());
ll.forEach((k) -> System.out.println(k.getId()+" & "+k.getName()));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With