Collectors.groupingBy(classifier, downstream) signatue is not correct

Brian Goetz brian.goetz at
Sat Dec 7 09:27:06 PST 2013

Yes, the two would be basically identical from a client perspective, 
since the only appearance of A is in a type argument of Collector.  I 
think I may even have written it that way originally!  And I think what 
pushed me into doing it this way is that if the Collector's A argument 
is a wildcard, then the whole rest of the implementation can't use A 
either, but instead would have to use ? or Object.  For example:

         Supplier<A> downstreamSupplier = downstream.supplier();
         BiConsumer<A, ? super T> downstreamAccumulator = 
         BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
             K key = Objects.requireNonNull(classifier.apply(t), 
"element cannot be mapped to a null key");
             A container = m.computeIfAbsent(key, k -> 
             downstreamAccumulator.accept(container, t);

Being able to use A here in the implementation makes it more readable 
and enables more type checking.  And "A" shows up a lot in this code.

On 12/7/2013 11:57 AM, Remi Forax wrote:
> This is something, I have discovered with Paul during Devoxx,
> that I had forgotten until one of my student stubble on the very same
> issue Wednesday,
> it's not a big issue, it's just something annoying.
> Collectors.groupingBy that takes another collector as downstream
> collector is typed like this:
> public static <T, K, A, D>
>      Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends
> K> classifier,
>                                            Collector<? super T, A, D>
> downstream) {
>          ...
>      }
> here declaring A is useless because it is used only to type downstream.
> This is annoying because another rule of Java,
> when you specify implicitly a type argument for a type variable,
> you cannot use '?' even if the type variable appears in place where '?'
> is allowed.
> So the compiler is able to capture a wildcard to a type varaible but
> a user can not do the same thing explicitly.
> My student was trying to understand why the compiler was not compiling
> its code (hint: he fails to check the spelling first) and to isolate the
> issue, he was trying to explicitly specify the type argument.
> I think the signature of groupBy (the one that takes a downstream)
> should be
>    public static <T, K, D>
>      Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends
> K> classifier,
>                                            Collector<? super T, ?, D>
> downstream) {
>          ...
>      }
> (the declaration of A is removed and A is replaced by '?')
> cheers,
> Rémi

More information about the lambda-libs-spec-observers mailing list