如何使用Java8流从嵌套对象组装Map <Key,Value>?

Jav*_*Fan 2 java dictionary java-8 java-stream collectors

假设我有3辆汽车,每辆汽车有3个发动机,每个发动机有3个零件.如何map of <engine_model, List<parts>>使用Java8流创建一个?

在常规Java中,我会执行以下操作:

Map<String, List<Parts>> map = new HashMap<String, List<Parts>>();
for (Car car: cars){
  for (Engine engine: car.getEngines()){
    if (!map.contains(engine.getModel())){
      map.put(engine.getModel(), new ArrayList<Part>());
    }
    for (Part  part: engine.getParts()){
      map.get(engine.getModel()).add(part);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

map是一个map将引擎的model(type String)映射到与该模型相关的所有部件的列表.不同的车可以有相同的发动机型号.

我试着做以下事情:

carList.stream().flatMap(p -> p.getEngines().stream())
  .collect(Collectors.groupingBy(p -> p.getModel(),
               Collectors.mapping(Engine::getParts, Collectors.toList())))
Run Code Online (Sandbox Code Playgroud)

问题是上面的使用我得到了 Map<String, List<List<Part>>> 我想要的 Map<String, List<Part>>

我想一个等效的问题是:我怎么改变List of Lists,只是List在上面的例子中的情况下?

Hol*_*ger 7

首先,您甚至可以简化您的命令式变体:

Map<String, List<Part>> map = new HashMap<>();
for(Car car: cars) {
    for(Engine engine: car.getEngines()) {
        map.computeIfAbsent(engine.getModel(), key -> new ArrayList<>())
           .addAll(engine.getParts());
    }
}
Run Code Online (Sandbox Code Playgroud)

在决定功能变体是否真的是一种改进时,这一点很重要.该flatMap+ groupingBy集电极是正确的做法,但你有一个列表(的事实PartS)扁平化是一个额外的障碍.在Java 9中,您可以编写

Map<String, List<Part>> map = cars.stream()
    .flatMap(car -> car.getEngines().stream())
    .collect(Collectors.groupingBy(Engine::getModel,
                 Collectors.flatMapping(e -> e.getParts().stream(), Collectors.toList())));
Run Code Online (Sandbox Code Playgroud)

但在那之前,我们必须手动组装一个等效的收集器:

Map<String, List<Part>> map = cars.stream()
    .flatMap(car -> car.getEngines().stream())
    .collect(Collectors.groupingBy(Engine::getModel,
                 Collector.of(ArrayList::new, (l,e) -> l.addAll(e.getParts()),
                              (l1,l2) -> { l1.addAll(l2); return l1; })));
Run Code Online (Sandbox Code Playgroud)

所以我现在考虑继续使用循环.