Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot Infer Type Variables for Collectors.toMap

I'm trying to create an EnumMap that simply maps the enum's constants to their respective ordinals. I figured I could do so succinctly like so:

private static Map<Rank, Integer> defaultRankOrdering = new EnumMap<>(
    Arrays.stream(Rank.values()).collect(
        Collectors.toMap(Function::identity, e -> e.ordinal())));

However, the compiler says it cannot infer any of the type variables for toMap. I don't see why, considering that, per the two-argument signature of toMap:

public static <T, K ,U> Collector<T, ? ,Map<K, U>> toMap(Function<? super T, ? extends K> keyMapper,
                                                         Function<? super T, ? extends U> valueMapper)

T should be inferred to be Rank, as Arrays.stream(Rank.values()) is a Stream<Rank>, K should also be inferred to be Rank, as Function.identity returns a Function<T, T>, and U should be inferred to be Integer because the return type of Enum.ordinal is int, which should be boxed to Integer in this case.

Any help would be greatly appreciated.

like image 714
Isaac Saffold Avatar asked Jul 09 '17 20:07

Isaac Saffold


Video Answer


2 Answers

You want Function.identity(), not Function::identity :

private static Map<Rank, Integer> defaultRankOrdering = new EnumMap<>(
    Arrays.stream(Rank.values()).collect(
        Collectors.toMap(Function.identity(), e -> e.ordinal())));

The type of Function::identity is Supplier<Function<T,T>>, since it's a method reference for a method that takes nothing and returns a Function<T,T>.

What you need for your key mapping function is a Function<T,T>, which is returned by simply calling the method Function.identity().

like image 108
Eran Avatar answered Sep 27 '22 18:09

Eran


Even if @Eran has pointed out your problem, but I think you need this code snippet, so write it down in my answer:

static Map<Rank, Integer>
defaultRankOrdering = Arrays.stream(Rank.values()).collect(toMap(
        Function.identity(),
        Enum::ordinal,
        (v1, v2) -> v1, // it'is never be used, only support for create an EnumMap
        () -> new EnumMap<>(Rank.class)
));
like image 37
holi-java Avatar answered Sep 27 '22 17:09

holi-java