Stream.flatMap reference ambiguity

Maurizio Cimadamore maurizio.cimadamore at
Tue Feb 26 10:09:08 PST 2013

On 26/02/13 17:24, Sam Pullara wrote:
> Doesn't help. You need to specify the types. It would be great if this were fixed either in the API or in the inference engine:
>        List<String> ss = new ArrayList<>();
> x, Consumer<String> sink) -> {
>          for (String s : x.split(",")) {
>            sink.accept(s);
>          }
>        });
Never say never ;-)

Turns out that my first stab at the code was wrong as it didn't take 
into account something that we have included in the spec: if a lambda 
contains errors (i.e. as a result of the choice of bad parameter types 
from the target) the method is not applicable.

Now - in this example there are three potentially applicable methods 
(after provisional applicability):

1) <R> Stream<R> flatMap(FlatMapper<? super T, R> mapper) // (T, Consumer<R>)void
2)IntStream flatMap(FlatMapper.ToInt<? super T> mapper); // (int, IntConsumer)void
3)LongStream flatMap(FlatMapper.ToLong<? super T> mapper); // (long, LongConsumer)void
4)DoubleStream flatMap(FlatMapper.ToDouble<? super T> mapper); // (double, DoubleConsumer)void


the first parameter type inferred from the descriptor is interesting: it 
can be either T (the type of the Stream, String in this case), int, long 
or double. But if you look at the code, it contains this snippet:


This will only compile when x has type String - which means only method 
(1) is applicable, no ambiguity should be issued.

I'm actually in the process of updating the compiler to reflect that 
rule in the spec, and I found that it compiles this example just fine, 
even w/o explicit types. I'll push a patch soon.


> Sam
> On Feb 26, 2013, at 9:06 AM, Zhong Yu <zhong.j.yu at> wrote:
>> On Tue, Feb 26, 2013 at 7:57 AM, David Hartveld <david at> 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);
>>> }
>>> });
>> This example is not very realistic, since the result of flatMap() is
>> not used, the code doesn't really do anything. What if it's assigned
>> to a `Stream<String>`?
>>> 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