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());

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
ab11
  • 19,770
  • 42
  • 120
  • 207

3 Answers3

4

flatMap should help you :

return myList.stream()
        .flatMap(x -> expand(x).stream())
        .collect(Collectors.toList());
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
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
  • 125,838
  • 23
  • 214
  • 215
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
  • 763
  • 9
  • 14