Retrieve distinct element based on multiple attributes of java object using java 8 stream

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 :

  • Thank you Stuart Marks for the useful distinctByKey method
  • https://www.concretepage.com/java/jdk-8/java-8-distinct-example
  • https://howtodoinjava.com/java-8/java-stream-distinct-examples/
  • demo ideone

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