2

Can someone explain this to me, why does not this expression type get automatically inferred by the compiler ?

Stream.empty().collect(Collectors.summingInt(CharSequence::length))

We know that CharSequence::length in this context is a ToIntFunction<CharSequence>, so the type being consumed from the stream elements is a CharSequence, therefore, the stream being collected is of type Stream<CharSequence>.

On my IDE, I get the following error :

The method collect(Collector<? super Object,A,R>) in the type Stream is not applicable for the arguments (Collector<CharSequence,capture#1-of ?,Integer>)

As you can see from the error message, the Stream.empty() gets auto inferred to a Stream<Object> which is definitely not what I want !

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
  • 1
    This is a known limitation. The target type is not propagated through *chained* method invocations. Here, `Stream.empty()` and `collect(Collectors.summingInt(CharSequence::length))` are chained. This is explained [here](https://stackoverflow.com/a/26883991/2711488) and [here](https://stackoverflow.com/a/25173599/2711488). – Holger Oct 11 '18 at 08:28

1 Answers1

4

Java's Stream.empty() is a generic method with the following declaration.

public static<T> Stream<T> empty() {
   // Remainder omitted.
}

So you have to pass the type parameters explicitly. Otherwise it will create a Stream of type java.lang.Object. So change your declaration like so to get rid of the error.

Stream.<CharSequence>empty().collect(Collectors.summingInt(CharSequence::length));

Java won't infer the type based on data types used in downstream operations in your stream processing pipeline. The type resolution algorithm is not that smarter as you think. However it will infer if you pass the values to the factory method. For an instance this will work.

Stream.of("ab", "abc").collect(Collectors.summingInt(CharSequence::length));
Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
  • Thank you by the way for your answer, the problem is that I know how to fix the problem this way by explicitly setting the type parameter early in the `Stream.empty()` method. The problem is why java did not auto infer this from the context, i mean, i did collect the stream by a `Collector`, this must give a clue to java about the type of the input elements which is `CharSequence` no ? – marsouf Oct 11 '18 at 08:09