映射的嵌套流 Java 11

Nested streams to a Map Java 11

假设您有一个接口、几个实现 类 和一个像这样的枚举: 接口:

public interface Employee {
    // No two employees will have same favorite hobbies
    List<Hobby> favoriteHobbies; 
}

实施:

public class Employee1 implements Employee {
    @Override
    public List<Hobby> favoriteHobbies {
        return List.of(Hobbies.swimming, Hobbies.dancing);
    }
}

public class Employee2 implements Employee {
    @Override
    public List<Hobby> favoriteHobbies {
        return List.of(Hobbies.running);
    }
}

枚举:

public enum Hobby {
    swimming,
    running,
    dancing
}

我有 List<Employee> employees = List.of(Employee1, Employee2);

并且使用 Streams,我想通过 employees 列表进行流式传输,然后再次通过每个 Employee 对象的 favoriteHobbies() 进行流式传输,并创建一个如下所示的 Map<Hobby, Employee>

"swimming" -> "Employee1"
"dancing" -> "Employee1"
"running" -> "Employee2"

我会在 Stream 中创建一个 Map.Entry,然后使用它的键和值收集它

因为 这可以使用 Stream#mapMulti

Map<Hobby, Employee> map = employees.stream()
        .mapMulti((Employee employee, Consumer<AbstractMap.SimpleEntry<Hobby, Employee>> consumer) -> {
            employee.favoriteHobbies().forEach(hobby -> {
                consumer.accept(new AbstractMap.SimpleEntry<>(hobby, employee));
            });
        })
        .collect(Collectors.toMap(
                AbstractMap.SimpleEntry::getKey,
                AbstractMap.SimpleEntry::getValue,
                (entryOne, entryTwo) -> entryOne // or whatever, maybe even throw new XXXException()
        ));

之前,可以使用 Stream#flatMapCollectors#toMap

Map<Hobby, Employee> map = employees.stream()
        .flatMap(employee -> employee.favoriteHobbies()
                .stream()
                .map(hobby -> new AbstractMap.SimpleEntry<>(hobby, employee)))
        .collect(Collectors.toMap(
                AbstractMap.SimpleEntry::getKey,
                AbstractMap.SimpleEntry::getValue,
                (entryOne, entryTwo) -> entryOne // or whatever, maybe even throw new XXXException()
        ));

产生

因为 Java 9 可以使用 Map.entry,还应该构造一个 LinkedHashMap 来维护映射条目的插入顺序:

Map<Hobby, Employee> map = employees()
    .stream()
    .flatMap(e -> e.favoriteHobbies().stream().map(h -> Map.entry(h, e)))
    .collect(Collectors.toMap(
        Map.Entry::getKey, 
        Map.Entry::getValue, 
        (a, b) -> a, 
        LinkedHashMap::new
    ));

但是,如果输入 employees 列表包含多个不同实现的实例,使用 Stream::flatMapCollectors::groupingBy 构建映射 Map<Hobby, List<Employee>> 会更有意义Collectors::mapping, Collectors::toList:

List<Employee> employeeList = List.of(
    new Employee1("John"), new Employee1("Jack"), new Employee2("Jeff"),
    new Employee1("Jake"), new Employee2("Jean")
);
Map<Hobby, List<Employee>> mapList = employees()
    .stream()
    .flatMap(e -> e.favoriteHobbies().stream().map(h -> Map.entry(h, e)))
    .collect(Collectors.groupingBy(
        Map.Entry::getKey, 
        LinkedHashMap::new, 
        Collectors.mapping(Map.Entry::getValue, Collectors.toList())         
    ));