As was told above you are trying to use raw Stream. If you want to iterate across Integer then you need to specify generic for Stream.
For instance
Stream<Integer> st = Stream.of(1,2,3,4);
Then it will compile.
This probalem is equuvalent to problem with iterating across generic colection in old style
Collection values = Arrays.asList(1,2,3,4);
for(Integer v: values){
System.out.println(v);
}
The code above won't compile because values is list of objects not integers.
As for averagingInt it will compile even if you will provide a list of String. For instance
Stream st = Stream.of("1","2","3","4");
st.collect(Collectors.averagingInt((Integer x)->x));
However it will failed during runtime with ClassCastException. The difference here is that averagingInt tryes to cast all incoming types to specific and forEach just uses types as is what may cause compilation fail.
It is equivalent
ToIntFunction<? super Integer> mapper = new ToIntFunction<Integer>(){
@Override
public int applyAsInt(Integer value) {
return value;
}
};
st.collect(Collectors.averagingInt(mapper));
The anonymous class will be used inside of averagingInt and before passing args to applyAsInt method it will be cast to appropriate type (in my sample to Integer )
Another interesting thing
Stream st = Stream.of(1,2,3,4);
Consumer<String> stringConsumer = new Consumer<String>() {
@Override
public void accept(String o) {
}
};
st.forEach(stringConsumer); // will compile disregarding to raw type of Stream and specific Consumer
st.forEach((Integer a) -> System.out.println(a)); // will fail because os raw Stream