Search code examples
javafunctional-programmingjava-streamfunctional-interface

How to apply in Function<T, R> argument from List (not List)


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())));

Solution

  • 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.