javajava-8java-streammethod-reference

Concat Stream of String and Integer


I am learning Stream and during one such practice session i was trying to join 2 streams of different type String and Integer via below code:

Stream<String> fruitStream = Stream.of("Apple", "Mango", "Muskmalon", "Guvava");
Stream<Integer> vegetablesStream = Stream.of(1, 2, 3, 4);

Stream<String> mixStream = Stream.concat(fruitStream, vegetablesStream.map(i -> i.toString()));
mixStream.forEach(System.out :: println);

It worked properly and gave me desired result.

Then i tried using Method Reference:

Stream<String> mixStream = Stream.concat(fruitStream, vegetablesStream.map(Integer :: toString));

And it started throwing error:

Wrong 1st argument type. Found: 'java.util.stream.Stream<java.lang.String>', required: 'java.util.stream.Stream<? extends T>'
concat (java.util.stream.Stream<? extends T>, java.util.stream.Stream<? extends T>) in Stream cannot be applied to (java.util.stream.Stream<java.lang.String>, java.util.stream.Stream<R>)   
reason: No compile-time declaration for the method reference is found

When i replaced my Method Reference with String :: ValueOf, it is working fine:

Stream<String> mixStream = Stream.concat(fruitStream, vegetablesStream.map(String :: valueOf));

I am unable to understand why Integer :: toString failed but String :: valueOf passed?


Solution

  • The error message should be Ambiguous method reference: both toString() and toString(int) from the type Integer are eligible. That happens because both toString and toString(int) are eligible to be used here.

    It could have been both:

      .map(i -> i.toString(i))
      .map(i -> i.toString())      
    

    And it works fine because String::valueOf has no such overloaded method and thus the compiler is fine with that.