2

I have some code that looks like this.

class A {}
class B extends A {
    private String name; // assume there's a getter
}
class C extends A {
    private List<B> items = new ArrayList<>(); // assume a getter
}

In another class, I have an ArrayList (ArrayList<A>). I'm trying to map this list to get all the names.

List<A> list = new ArrayList<>();
// a while later
list.stream()
    .map(a -> {
        if (a instanceof B) {
            return ((B) a).getName();
        } else {
            C c = (C) a;
            return c.getItems().stream()
                .map(o::getName);
        }
    })
    ...

The problem here is that I end up with something like this (JSON for visual purposes).

["name", "someName", ["other name", "you get the idea"], "another name"]

How can I map this list so I end up with the following as my result?

["name", "someName", "other name", "you get the idea", "another name"]
Spedwards
  • 4,167
  • 16
  • 49
  • 106
  • Use a `flatMap`.. It would be useful if you show how you collect the result after the *map* step (the *else* returns a Stream whereas the *if* part returns a String). Are you collecting it into a `List`? – Thiyagu Jan 23 '19 at 08:27
  • take a look at https://stackoverflow.com/questions/26684562/whats-the-difference-between-map-and-flatmap-methods-in-java-8 it will help you understand the use of flatMap – mkjh Jan 23 '19 at 08:38

1 Answers1

4

Use flatMap:

list.stream()
    .flatMap(a -> {
        if (a instanceof B) {
            return Stream.of(((B) a).getName());
        } else {
            C c = (C) a;
            return c.getItems().stream().map(o::getName);
        }
    })
    ...

This will produce a Stream<String> of all the names, without nesting.

Eran
  • 387,369
  • 54
  • 702
  • 768