How to flatten list in java 8

Viewed 222
class Employee {
    private String name;
    private List<Employee> members;
}

List<Employee> emps = Arrays.asList(new Employee("A", Arrays.asList(
     new Employee("B", null),
     new Employee("C", null)
)))

The code to flatten the List:

List<Employee> total = 
    emps.stream()
        .flatMap(emp -> emp.members.stream())
        .collect(Collectors.toList());

The total List should have 3 elements, but it only has 2.

3 Answers

Eran's answer is wrong, there is no concat on Stream instance. This should work:

emps.stream()
        .flatMap(emp -> Stream.concat(emp.members.stream(), Stream.of(emp)))
        .collect(Collectors.toList());

Stream#concat

Alternative solution is:

List<Employee> total = emps.stream()
                      .collect(ArrayList::new,
                               (l, e) -> {l.add(e);l.addAll(e.getMembers());},
                               List::addAll);

Your stream pipeline only returns the Employees referenced by other Employees. It doesn't keep the Employees of the outer input List.

To get all the Employees you can change your flatMap to concatenate the current Employee to the Employees it references:

List<Employee> total = 
    emps.stream()
        .flatMap(emp -> Stream.concat(emp.members.stream(),Stream.of(emp)))
        .collect(Collectors.toList());

or (if you prefer the outer Employee to come before the corresponding referenced Employees):

List<Employee> total = 
    emps.stream()
        .flatMap(emp -> Stream.concat(Stream.of(emp),emp.members.stream()))
        .collect(Collectors.toList());

Note that the result might contain duplicates. You can eliminate them by adding distinct() after flatMap() (assuming your Employee class overrides equals() and hashCode()).

Related