Leon
Leon

Reputation: 364

Stream<Object> instead of Stream<? extends T> being produced when invoked on list

I have this method:

public static <T,U,R> Stream<R> cartesian(
    List<? extends T> list1,
    List<? extends U> list2,
    BiFunction<? super T, ? super U, R> func) 
{
    return list1.stream() // list1.stream() produces Stream<Object> not Stream<? extends T>!
        .flatMap(x -> {
            return list2.stream()
                .map(appendable ->x + "" +appendable);
        });
}

Because of the following error, my whole pipeline now return a Stream<Object> instead of the intended Stream<R>.

Any reasons why this error occur which I arrowed occurs?

Upvotes: 2

Views: 395

Answers (1)

Sweeper
Sweeper

Reputation: 271575

The "expected type: ... actual type: ..." message is not about list1.stream(), it's about the value you return in the lambda in flatMap. Observe where the red squiggles are:

enter image description here

It's saying that the code in the x -> ... lambda is returning a Stream<Object>, rather than the expected Stream<R>.

Note that map(spendable -> x + "" + appendable) can totally return a Stream<Object> with the right type arguments ( if it were .<Object>map(appendable ->x + "" +appendable) for example).

And in fact, the "expected type: ... actual type: ..." message is only produced by IntelliJ, so it's probably just IntelliJ being a bit silly. If you run javac, you get a much better error message:

incompatible types: inference variable R#1 has incompatible bounds
        .flatMap(x -> {
                ^
    equality constraints: R#2
    lower bounds: R#3,String
  where R#1,T#1,R#2,T#2,U,R#3 are type-variables:
    R#1 extends Object declared in method <R#1>flatMap(Function<? super T#1,? extends Stream<? extends R#1>>)
    T#1 extends Object declared in interface Stream
    R#2 extends Object declared in method <T#2,U,R#2>cartesian(List<? extends T#2>,List<? extends U>,BiFunction<? super T#2,? super U,R#2>)
    T#2 extends Object declared in method <T#2,U,R#2>cartesian(List<? extends T#2>,List<? extends U>,BiFunction<? super T#2,? super U,R#2>)
    U extends Object declared in method <T#2,U,R#2>cartesian(List<? extends T#2>,List<? extends U>,BiFunction<? super T#2,? super U,R#2>)
    R#3 extends Object declared in method <R#3>map(Function<? super T#1,? extends R#3>)

That says that the type parameter R in flatMap cannot be inferred, because its bounds cannot be satisfied simultaneously. R in flatMap has to be the same as the R in cartesian, but its lower bounds are R in map, and String.

Anyway, it seems like what you wanted to do was:

return list1.stream()
    .flatMap(x -> list2.stream().map(y -> func.apply(x, y)));

Upvotes: 2

Related Questions