4

I am trying to flatten my String[] stream to a String Stream

E.g.

{ "A", "B", "C" }, {"D, "E" } to "A", "B", "C", "D", "E"

This is the code I have so far:

Files.lines(Paths.get(file)).map(a -> a.split(" "));

Files.lines(path) returns Stream[String] and I split every string by " " to get an array of all the words ( so now Stream<String[]>.

I would like flatten each array of words into individual elements , so Stream[String] instead of Stream<String[]>

When i use flatMap instead of map I get an error : Type mismatch: cannot convert from String[] to Stream<? extends Object>

I thought flatMap is used for this purpose? What's the best way to accomplish what I am trying to do


Question from professor:

Using streams : Write a method to classify words in a file according to length:

public static Map<Integer,List<String>> wordsByLength(String file) 
throws IOException {
   // COMPLETE THIS METHOD
}
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
noobcoder24
  • 135
  • 1
  • 13

3 Answers3

7
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

A Stream#flatMap mapper expects a Stream to be returned. You are returning a String[]. To turn a String[] into a Stream<String>, use Arrays.stream(a.split(" ")).

The complete answer to your assignment:

public static Map<Integer, List<String>> wordsByLength(String file)
        throws IOException {
    return Files.lines(Paths.get(file))
                .flatMap(a -> Arrays.stream(a.split("\\s+")))
                .collect(Collectors.groupingBy(String::length));
}
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
3

The function you pass to flatMap must return a stream, not an array.

e.g.

.flatMap(a -> Arrays.stream(a.split(" ")))
khelwood
  • 55,782
  • 14
  • 81
  • 108
0

You need the .flatMap() operation :

  • after the normal .map() operation

    Files.lines(Paths.get(file)).map(a -> a.split(" ")).flatMap(Arrays::stream);
    
  • combined with normal map operation:

    Files.lines(Paths.get(file)).flatMap(a -> Arrays.stream(a.split(" ")));
    

At the end you'll need

public static Map<Integer, List<String>> wordsByLength(String file) throws IOException {
    return Files.lines(Paths.get(file))                      //Stream<String>
            .map(a -> a.split(" "))                          //Stream<String[]>
            .flatMap(Arrays::stream)                         //Stream<String>
            .collect(Collectors.groupingBy(String::length)); //Map<Integer, List<String>>
}
azro
  • 53,056
  • 7
  • 34
  • 70