将 Map<K, List<V>> 转换为 Map<K, V>,其中 V 有 2 个对象列表

Convert Map<K, List<V>> to Map<K, V> where V have 2 lists of objects

型号:

Year{
 int year;
}

ObjectB{
 ObjectBA bb;  <- ObjectBA{int value}
 ObjectBB ba;  <- ObjectBB{int value}
}

ObjectC{
  List<ObjectBA>
  List<ObjectBB>
}

转换方式: Map<Year, List<ObjectB>> Map<Year, ObjectC> 其中对象 C 具有来自对象 B

的所有元素

我已经有:

var result = inputMap.entrySet().stream()
             .collect(Collectors.toMap(
                        e -> e.getKey(),
                        e -> e.getValue().stream().
                                map(
                                       value -> value.bb().getValue()
                                ).toList())
                );

我需要在对象中给我多个列表的东西,比如:

 map(
       new ObjectC(
          value -> value.ba().getValue(),
          value -> value.bb().getValue()
    ).toList())

你得到的看起来已经很不错了。只需将值映射器替换为 e -> convert(e.getValue()),其中 convert 就像下面将 List<ObjectB> 转换为 ObjectC 的函数:

ObjectC convert(List<ObjectB> list) {
    ObjectC c = new ObjectC();
    for (ObjectB b : list) {
        c.ba.add(b.ba);
        c.bb.add(b.bb);
    }
    return c;
}

或者,如果您更愿意坚持只使用流,请尝试 Stream#collect,如下所示:

e.getValue().stream().collect(
        () -> new ObjectC(),
        (c, b) -> {
                c.ba.add(b.ba);
                c.bb.add(b.bb);
        },
        (c1, c2) -> {
                c1.ba.addAll(c2.ba);
                c1.bb.addAll(c2.bb);
        }
)

为了将来可能的参考,我提供以下内容:

第一个是基于简单循环的解决方案。在这两者中,这更直接并且可能更有效。

  • 迭代地图的条目集。
  • 创建两个列表,每个列表对应 ObjectC
  • 的每个字段
  • 然后遍历 ObjectB 列表并将对象复制到它们的列表中
  • 然后使用新创建的列表创建 ObjectC 的实例

我使用了 getter 和构造函数,但如果字段不是私有的,则可以使用直接赋值。

for (Year y : map.keySet()) {
    List<ObjectBA> listBA = new ArrayList<>();
    List<ObjectBB> listBB = new ArrayList<>();
    for (ObjectB b : map.get(y)) {
        listBA.add(b.getBA());
        listBB.add(b.getBB());
    }
    result.put(y, new ObjectC(listBA, listBB));
}

此方法使用流。

  • 流式传输 entrySet。
  • 并使用构造函数创建一个新的 ObjectC。
  • 构造函数的参数本身,源列表的流
  • 执行映射以获取对象(BA 和 BB)
  • 并返回一个列表以满足构造函数的要求。
Map<Year, Object> result = map.entrySet().stream().collect(
        Collectors.toMap(Entry::getKey,
                e -> new ObjectC(
                e.getValue().stream().map(ObjectB::getBA)
                        .toList(),
                e.getValue().stream().map(ObjectB::getBB)
                        .toList())));