5

Question based on https://stackoverflow.com/a/29671501/2517622

Given a list of employees with id, name and IQ:

List<Employee> employee = Arrays.asList(new Employee(1, "John", 80), new Employee(1, "Bob", 120), Employee(1, "Roy", 60), new Employee(2, "Alice", 100));

I want to output:

[Employee{id=1, name='Bob', iq=120}, Employee{id=2, name='Alice', iq=100}]

So, remove duplicates from the list based on id property of employee and choose employee with the highest IQ for obvious reasons. :)

Particularly, I am interested in adjusting this solution which removes duplicates only based on id:

    import static java.util.Comparator.comparingInt;
    import static java.util.stream.Collectors.collectingAndThen;
    import static java.util.stream.Collectors.toCollection;

    ...
    List<Employee> unique = employee.stream()
                                    .collect(collectingAndThen(toCollection(() -> new TreeSet<>(comparingInt(Employee::getId))),
                                                               ArrayList::new));

Is there a way?

drets
  • 2,583
  • 2
  • 24
  • 38
  • 5
    `List unique = employee.stream() .collect(collectingAndThen(toMap(Employee::getId, Function.identity(), BinaryOperator.maxBy(Comparator.comparingInt(Employee::getIq))), m -> new ArrayList<>(m.values())));` – Holger Mar 28 '19 at 15:28

1 Answers1

7

How about this,

Collection<Employee> distinctEmps = employee.stream()
    .collect(Collectors.toMap(Employee::getId, Function.identity(), 
        (e1, e2) -> e1.getIq() >= e2.getIq() ? e1 : e2))
    .values();

Another variant by merely following @Holgers approach would be,

Collection<Employee> distinctEmps = employee.stream()
    .collect(Collectors.toMap(Employee::getId, Function.identity(), 
        BinaryOperator.maxBy(Comparator.comparing(Employee::getIq))))
    .values();
Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63