Stream.flatMap reference ambiguity

Maurizio Cimadamore maurizio.cimadamore at
Tue Feb 26 06:15:35 PST 2013

On 26/02/13 13:57, David Hartveld wrote:
> Hi all,
> I just ran into the following problem with flatMap: the compiler
> (lambda-b78) is not able to infer the correct overload for flatMap.
> The code:
> List<String> ss = new ArrayList<>();
>, sink) -> {
> for (String s : x.split(",")) {
>   sink.accept(s);
> }
> });

The compiler is correct, at least according to the spec. the two SAMs 
are like:


        69      interface ToLong<T> {

        70          /**

        71           * Accept an input element and emit zero or more output elements into the provided {@code LongConsumer}

        72           * @param element The input element

        73           * @param sink A {@code LongConsumer} to receive the output elements

        74           */

        75          void flattenInto(T element, LongConsumer sink);

        76      }



        83      interface ToDouble<T> {

        84          /**

        85           * Accept an input element and emit zero or more output elements into the provided {@code DoubleConsumer}

        86           * @param element The input element

        87           * @param sink A {@code DoubleConsumer} to receive the output elements

        88           */

        89          void flattenInto(T element, DoubleConsumer sink);

        90      }

Both descriptors are void, so the compiler cannot use the usual trick of 
picking the SAM with the most specific return type. Another problem is 
that the return-type trick is currently only applied if the descriptor 
parameter lists match - which is also not the case here. I think this 
calls for some sort of API refactoring.

> The compiler output:
>[38,28] reference to flatMap is ambiguous
> both method flatMap(<? super T>) in
> and method
> flatMap(<? super T>) in
> match
>[40,37] method accept in interface
> java.util.function.LongConsumer cannot be applied to given types;
> required: long
> found: java.lang.String
> reason: argument mismatch; java.lang.String cannot be converted to long
> This can be solved by typing the lambda parameters (actually, exactly that
> is done in the default implementation of Stream.flatMap(Function<T,
> Stream<? extends R>>).
> Is this a bug/unimplemented inference situation? If not, I would prefer a
> rename of the flatMap overloads that return a primitive stream (these cause
> the ambiguity, right?). I think it is confusing that, when using the Stream
> API (or any other coherent API), you have to specify types in some lambdas,
> and not in others - I find this confusing, and it probably is even more so
> for less advanced programmers.
> Thanks in advance for a great-looking update to the JDK!
> Regards,
> David Hartveld

More information about the lambda-dev mailing list