Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java forEach not working on flatMap using IntStream.range

Starting with this trivial example from java2s:

 Stream.of("XML", "Java",  "CSS")
.flatMap(name ->  IntStream.range(0, name.length()).mapToObj(name::charAt))
.forEach(System.out::println);

the output is

X
M
L
J
a
v
a
C
S
S

I'm trying to understand what's going on inside the flatMap. I'd like to see the output of the IntStream.range, but I cannot get it to work. It seems you can whack a forEach(SOP) onto an IntStream.range(a,b) but when it's inside of the flatMap function, that can't be done (and I didn't at first notice that the whole of name -> IntStream.range(0, name.length()).mapToObj(name::charAt) is the argument to the flatMap function. How could I use the flatMap function with IntStream.range to convert the strings to a sequence of numbers corresponding to the lengths of the words?

I have tried this:

 Stream.of("XML", "Java",  "CSS")
        .flatMap(name ->  IntStream.range(0, name.length())) 
        .forEach(System.out::println);

but it does not compile. I was expecting the line

.flatMap(name ->  IntStream.range(0, name.length())) 

to take the strings and convert them to 0,1,2,0,1,2,3,0,1,2. What am I misunderstanding? How can I get this sequence of numbers using the output of name -> IntStream.range(0, name.length())?
Thank you in advance.

like image 908
JL_SO Avatar asked Jul 13 '18 00:07

JL_SO


1 Answers

The compiler error is:

/MyClass.java:6: error: incompatible types: cannot infer type-variable(s) R
                .flatMap(name ->  IntStream.range(0, name.length())) 
                        ^
    (argument mismatch; bad return type in lambda expression
      IntStream cannot be converted to Stream<? extends R>)
  where R,T are type-variables:
    R extends Object declared in method <R>flatMap(Function<? super T,? extends Stream<? extends R>>)
    T extends Object declared in interface Stream
1 error

The important bit is:

IntStream cannot be converted to Stream<? extends R>

An IntStream is a form of stream optimized for integers, but it's not directly compatible with Stream<Integer>.

You need to either call boxed() to convert it to a stream of objects:

Stream.of("XML", "Java",  "CSS")
        .flatMap(name ->  IntStream.range(0, name.length()).boxed()) 
        .forEach(System.out::println);

Or call flatMapToInt:

Stream.of("XML", "Java",  "CSS")
        .flatMapToInt(name ->  IntStream.range(0, name.length())) 
        .forEach(System.out::println);

You had the right idea, just needed a little tweaking to make Java understand you.

like image 105
John Kugelman Avatar answered Oct 20 '22 01:10

John Kugelman