3

I have a method which returns company as key and list of employeer as values <T> Map<String, List<T>> getUserPerCompany(final Function<User, T> converter). The method accepts the converter parameter which in the tests returns the String (name + lastname of the employee). It should returns: Map<String, List<String>>. I created this implementation:

return getUserStream().collect(toMap(Company::getName, c -> converter.apply(c.getUsers())));

Error is: apply (domain.User) in Function cannot be applied to (java.util.List<domain.User>)

My problem is that I do not know how to pass the employee to the 'apply' list instead of the list in full.

My other attempts:

  • return getUserStream().collect(toMap(Company::getName, c -> converter.apply((User) c.getUsers().listIterator())));
  • return getUserStream().collect(toMap(Company::getName, c -> converter.apply((User) c.getUsers().subList(0, c.getUsers().size()))));
  • return getUserStream().collect(toMap(Company::getName, c -> converter.apply((User) c.getUsers().iterator())));
Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
pancake
  • 63
  • 7

2 Answers2

2

I suppose this is what you're looking for

<T> Map<String, List<T>> getUserPerCompany(final Function<User, T> converter) {
    return getUserStream().collect(Collectors.toMap(
            c -> c.getName(),
            c -> c.getUsers()
                  .stream()
                  .map(converter)
                  .collect(Collectors.toList())
    ));
}

Usage example is

final Map<String, List<String>> users = getUserPerCompany(user -> user.getName() + " " + user.getSurname());

Basically you need to map each User, applying the input Function.

LppEdd
  • 20,274
  • 11
  • 84
  • 139
  • 2
    Thank you very much! I have just replaced `getUserStream ()` with `getCompanyStream ()` (companies contain users) but these are my internal methods that are not here. Thank you again for the solution, it works and it is clear. – pancake Mar 03 '19 at 14:17
0

You can use Collectors.groupingBy() and write custom Collector:

<T> Map<String, List<T>> getUserPerCompany(final Function<User, T> converter) {
    return getUserStream().collect(
            Collectors.groupingBy(
                    c -> c.getName(),
                    Collector.of(
                            ArrayList::new,                  //init accumulator
                            (list, c)-> c.getUsers()         //processing each element
                                         .stream()
                                         .map(converter)
                                         .forEach(list::add),
                            (result1, result2) -> {          //confluence 2 accumulators 
                                result1.addAll(result2);     //in parallel execution
                                return result1;
                            }
                    )
            )
    ); 
}
kozmo
  • 4,024
  • 3
  • 30
  • 48