2

I was wondering how I could use Java Stream API to flatten a structure where I have an object and a collection of the same type objects nested in it.

What I mean is that I have a Component class which has a field of type List<Component>. What I would like to do is find a neat, stream solution that would the the same as the following code (I need to end up with a list of all components and nested subcomponents).

List<Component> components = getComponents(id);
List<Component> componentsAndSubcomponents = new ArrayList<>();
for (Component component : components) {
  componentsAndSubcomponents.add(component);
  componentsAndSubcomponents.addAll(component.getSubComponents());
}
Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
furry12
  • 902
  • 1
  • 14
  • 31

2 Answers2

3

You can use flatMap with Stream concatenation:

List<Component> componentsAndSubcomponents =
    components.stream()
              .flatMap(c -> Stream.concat(Stream.of(c),c.getSubComponents().stream()))
              .collect(Collectors.toList());

This will map each Component into a Stream that contains that Component followed by all of its sub-components, and flatten all these Streams into a flat Stream<Component>, to be collected into a List<Component>.

Eran
  • 387,369
  • 54
  • 702
  • 768
2

An easy solution is to create an inner stream on the fly, as in:

List<Component> result = components.stream()
    .flatMap(comp -> 
        Stream.concat(Stream.of(comp), comp.getSubComponents().stream()))
    .collect(Collectors.toList());
ernest_k
  • 44,416
  • 5
  • 53
  • 99