0

I would like to map each entry in my list by calling expand(), which returns multiple entries, and then collect the result as a list.

Without streams, I would accomplish this like:

    List<String> myList = new ArrayList<>();
    List<String> expanded = new ArrayList<>();
    for (String s : myList) {
        expanded.addAll(expand(s));
    }
    return expanded;

    private List<String> expand(String x) {
        return Arrays.asList(x, x, x);
    }

How can I accomplish this with streams? This gives a compilation error:

return myList.stream().map(this::expand).collect(Collectors.toList());

YCF_L
  • 51,266
  • 13
  • 85
  • 129
ab11
  • 19,320
  • 39
  • 109
  • 199

3 Answers3

4

flatMap should help you :

return myList.stream()
        .flatMap(x -> expand(x).stream())
        .collect(Collectors.toList());
YCF_L
  • 51,266
  • 13
  • 85
  • 129
4
return myList.stream().map(this::expand).collect(Collectors.toList());

returns List<List<String>> because myList.stream().map(this::expand) returns a stream typed as Stream<List<String>> as you pass to map() a variable declared List<String> variable and not String.

You don't want that.

So chain Stream.map() with Stream.flatMap() to amalgamate Stream<List<String>> to Stream<String> :

return myList.stream()
             .map(this::expand)
             .flatMap(x->x.stream())
             .collect(Collectors.toList());
davidxxx
  • 115,998
  • 20
  • 192
  • 199
3

use flatMap to convert the Stream<List<String> to a Stream<String>: return myList.stream().map(this::expand).flatMap(Collection::stream).collect(Collectors.toList());

dfogni
  • 742
  • 9
  • 13