Why are these Java 8 lambdas behaving differently during type conversions?

  • A+
Category:Languages
Stream st = Stream.of(1,2,3,4); 

Does this create a stream of Integers (By inferring at runtime) or a Stream of Objects?

st.collect(Collectors.averagingInt((Integer x)->x)); 

This line compiles fine.

st.forEach((Integer x)-> System.out.println(x)); 

This line does not compile. It gives a compilation error at (Integer x), saying expected object but found Integer. Why?

Why does it not complain the same for the averagingInt method above?

averagingInt takes the ToIntFunction interface with raw reference type as <? super T> and allowing Integer value. While forEach is taking the Consumer interface with the same raw reference type as <? super T> and the compiler is complaining for the Integer argument value.

 


Does this create stream of Integers (By inferring at runtime) or Stream of Objects ?

Generics do not exist at runtime, there is nothing to "infer" at runtime. Since you have used a raw type for the Stream st - it is a Stream<Object> if you want.

Well, even what you wrote for (and does compile):

st.collect(Collectors.averagingInt((Integer x)->x)); 

would not compile when you try to add the expected result:

Double i = st.collect(Collectors.averagingInt((Integer x) -> x)); 

I wonder if you re-write like below would make more sense:

Collector<Integer, ?, Double> collector = Collectors.averagingInt((Integer x) -> x); Double result = st.collect(collector); // does not compile 

Inference would work for Collectors.averagingInt, but since you have used Stream as raw - everything else is raw too.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: