2

Merry Christmas,

I was tinkering with some java.util.Streams when some irregular behavior caught my eye. I was simply trying to flatten a list containing several streams of integer values likes this example:

List<Stream> list = new ArrayList<>();
list.add(Stream.of( 1,2 ));
list.add(Stream.of( 3,4 ));

list.stream().flatMap( s -> s ).forEach( System.out::println );

This minimal code snippet works without any issue. And usually when I see a lambda expression like s -> s I think I'd be able to simply replace it with java.util.Function#identity() since it's pretty much the same however in doing so I came upon this compile-time issue:

D:\Development\Java\Playground\src\Main.java:15:30
java: incompatible types: cannot infer type-variable(s) R,T
    (argument mismatch; java.util.function.Function<java.util.stream.Stream,java.util.stream.Stream> cannot be converted to java.util.function.Function<? super java.util.stream.Stream,? extends java.util.stream.Stream<? extends java.lang.Object>>)

I myself cant quite explain the difference between using java.util.Function#identity() and s -> s. So why does this compile time issue occur? My guess is that it has something to do with type erasure but I am not certain and can't explain this for myself.

I am using OpenJDK v16.0.1.

L.Spillner
  • 1,772
  • 10
  • 19
  • 5
    Don't use raw types. – Sotirios Delimanolis Dec 24 '21 at 21:37
  • 1
    @SotiriosDelimanolis Oh... This is embarrassing. I absolutely forgot to declare the type of the stream which ultimately causes the error. Thank your for pointing this out to me. The code now works but still I can't quite figure out why the it didn't work before. Shouldn't raw types be equal to `Type`? In that case Function#identity would return a Function,Stream> which in the end should work since it's operating on a Stream containing `Stream which should fulfill the requirements of Stream#flatMap – L.Spillner Dec 24 '21 at 21:43
  • 3
    *Shouldn't raw types be equal to `Type`?* [No.](https://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it#:~:text=how's%20a%20raw%20type%20different%20from%20using%20%3Cobject%3E%20as%20type%20parameters%3F) And raw types have cascading effects on the code that uses them. – shmosel Dec 24 '21 at 22:54
  • You may want to look at: [Java 8 lambdas, Function.identity() or t ->t](https://stackoverflow.com/questions/28032827/java-8-lambdas-function-identity-or-t-t) – Nowhere Man Dec 24 '21 at 23:33
  • The compiler can warn you when you use raw types. It’s a good idea to enable all compiler warnings, and pay attention to them. Some of us even like using [-Werror](https://docs.oracle.com/en/java/javase/17/docs/specs/man/javac.html#option-Werror) when we build… – VGR Dec 25 '21 at 03:53

1 Answers1

0

Perhaps this is what you were going for. The type should be Stream<Integer>

List<Stream<Integer>> list = new ArrayList<>();
list.add(Stream.of( 1,2 ));
list.add(Stream.of( 3,4 ));

list.stream().flatMap( s -> s ).forEach( System.out::println );

prints

1
2
3
4
        
WJS
  • 36,363
  • 4
  • 24
  • 39