将 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())));
型号:
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())));