In this answer I attempted to create a static utility method to make a List
into a Map
:
public static <K, T> Map<K, T> toMapBy(List<T> list,
Function<? super T, ? extends K> mapper) {
return list.stream().collect(Collectors.toMap(mapper, Function.identity()));
}
It works just fine. However, I found that the method cannot be used in all the same contexts as the list.stream().collect(...)
expression. The method isn't as flexible.
List<Student> students = Arrays.asList();
Map<Long, Student> studentsById1 = students.stream()
.collect(Collectors.toMap(Student::getId, Function.identity()));
Map<Long, Student> studentsById2 = toMapBy(students, Student::getId);
Map<Long, Person> peopleById1 = students.stream()
.collect(Collectors.toMap(Student::getId, Function.identity()));
Map<Long, Person> peopleById2 = toMapBy(students, Student::getId); // compile error!
In this example, Student
is a subtype of Person
and has a getId
method that returns a Long
.
The last statement fails with incompatible types: inference variable T has incompatible bounds ...
(JDK 1.8.0_25). Is there a way to define the type parameters so that the static method will work in the same contexts as the expression it contains?