Isaac Saffold
Isaac Saffold

Reputation: 1185

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.

Upvotes: 5

Views: 2104

Answers (2)

Eran
Eran

Reputation: 393781

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

Upvotes: 6

holi-java
holi-java

Reputation: 30676

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

Upvotes: 3

Related Questions