Collectors.groupingBy(classifier, downstream) signatue is not correct
Brian Goetz
brian.goetz at oracle.com
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 =
downstream.accumulator();
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 ->
downstreamSupplier.get());
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