Assume I have a method with the following signature:
<T, U extends Comparable<? super U>> Comparator<T> method(Map<String, Function<? super T, ? extends U>> comparatorFunctionMap)
The method accepts a map of functions (with string keys) and creates a Comparator<T>
as a result (it isn't important how). Map values are instances of Function<? super T, ? extends U>
, so that they can be directly passed to Comparator.comparing()
.
How do I populate this map in a type-safe way? Say I have a class Person
with attributes name
and age
(and getters for them).
When I do the following:
Map<String, Function<? super Person, ? extends Comparable>> map1 = new HashMap<>();
map1.put("name", Person::getName);
method(map1);
I get a warning on lines 1 and 3. If I try this instead, for example:
Map<String, Function<? super Person, ? extends Comparable<?>>> map2 = new HashMap<>();
map2.put("name", Person::getName);
method(map2);
The third line is a compile error.
Is there a way to do this type-safely?
If you want to be able to add both Person::getName
and Person::getAge
in the map, you won't be able to use the method signature you propose because there is no U that is a supertype of both String, Integer and Comparable.
Essentially, your map is a Map<String, Function<T, Comparable<?>>
since the comparables are not related to each other type-wise.
I don't think you can get around it without using raw types, which could look like below. Note that you still have type safety (you must pass a Comparable
to the map).
static void m() {
Map<String, Function<Person, Comparable<?>>> map = new HashMap<>();
map.put("name", Person::getName);
map.put("age", Person::getAge);
Comparator<Person> c = method(map);
}
@SuppressWarnings(value = {"unchecked", "rawtypes"})
static <T> Comparator<T> method(String name, Map<String, Function<T, Comparable<?>>> comparatorFunctionMap) {
Function f = (Function) comparatorFunctionMap.get("age");
Comparator<T> c = Comparator.comparing(f);
return c;
}
The only (I think) limitation of this is that technically, one could pass a weird class say Weird implements Comparable<String>
that would probably cause a runtime error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With