英文:
How to convert LIst<Object> to Map<K, V> with using java stream
问题
我想将 `List<ObjectInList>` 转换成 `Map<K, V>`
class ObjectInList {
List<Long> listWithLong;
Map<String, Object> dataMap; // 这里有一个 'id' 键,我想要将这个 id 作为转换后的映射中的键
}
新的映射格式如下
String type; // 这个 type 是 dataMap 的值
List<Long> contents
在 List<Object>
中的每个对象可以有重复的 type
例如
///////// 转换前 ////////////
[
{
list: [1,2,3],
dataMap: {
type: "a",
}
},
{
list: [4,5,6],
dataMap: {
type: "b",
}
},
{
list: [7,8],
dataMap: {
type: "a",
}
},
]
///////////// 转换后 //////////
{
"a": [1,2,3,7,8],
"b": [4,5,6]
}
<details>
<summary>英文:</summary>
I want to convert `List<ObjectInList>` to `Map<K, V>`
class ObjectInList {
List<Long> listWithLong;
Map<String, Object> dataMap; // there is 'id' key, and i want to use this id as key in map to be converted
}
The new map format is like below
String type; // this type is value of dataMap.
List<Long> contents
each Object in `List<Object>` can have duplicated type
for example
///////// before converted ////////////
[
{
list: [1,2,3],
dataMap: {
type: "a",
}
},
{
list: [4,5,6],
dataMap: {
type: "b",
}
},
{
list: [7,8],
dataMap: {
type: "a",
}
},
]
///////////// after converted //////////
{
"a": [1,2,3,7,8],
"b": [4,5,6]
}
</details>
# 答案1
**得分**: 1
你可以使用`groupingBy`按`type`进行分组,并且使用`flatMapping`来展平`Long`数据的列表,并将其收集为单个列表。
```java
Map<String, List<Long>> res =
objectInList
.stream()
.collect(Collectors.groupingBy(
e -> e.getDataMap().get("type"),
Collectors.flatMapping(
e -> e.getListWithLong().stream(),
Collectors.toList())
));
英文:
You can use groupingBy
to group by type
and flatMapping
to flatten list of Long
data and collect as single list.
Map<String, List<Long>> res =
objectInList
.stream()
.collect(Collectors.groupingBy(
e -> e.getDataMap().get("type"),
Collectors.flatMapping(
e -> e.getListWithLong().stream(),
Collectors.toList())
));
答案2
得分: 0
我不确定为什么你需要 Map<String, Object> dataMap;
,当它本应只有一个值。为了简单起见,我已经修改了你的 ObjectInList
类如下:
class ObjectInList {
List<Long> listWithLong;
String type;
}
要获得分组列表,我们可以这样做:
Map<String, List<Long>> grouped =
objectInLists.stream()
.collect(
Collectors.toMap(
ObjectInList::getType,
ObjectInList::getListWithLong,
(oldList, newList) -> {
oldList.addAll(newList);
return oldList;
}));
解释:
toMap
方法 -
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
toMap
接受 keyMapper
,这里是 ObjectInList::getType
(根据类型进行分组),valueMapper
是 ObjectInList::getListWithLong
,由于我们有重复的键,我们需要提供一个 mergeFunction
,即 (oldList, newList) -> {oldList.addAll(newList); return oldList;}
。
根据文档:
一个合并函数,用于解决与同一键关联的值之间的冲突,如提供给 {@link Map#merge(Object, Object, BiFunction)}。
英文:
I'm not sure why do you need Map<String, Object> dataMap;
when it was supposed to have only one value. For simplicity, I have modified your ObjectInList
class as
class ObjectInList {
List<Long> listWithLong;
String type;
}
To get grouped list we can do -
Map<String, List<Long>> grouped =
objectInLists.stream()
.collect(
Collectors.toMap(
ObjectInList::getType,
ObjectInList::getListWithLong,
(oldList, newList) -> {
oldList.addAll(newList);
return oldList;
}));
Explanation:
toMap
method -
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
toMap
takes keyMapper
which is ObjectInList::getType
(to group based on type) and valueMaper is ObjectInList::getListWithLong
and as we have duplicate key we need to provide a mergeFunction
as (oldList, newList) -> {oldList.addAll(newList);return oldList;}
From documentation -
> a merge function, used to resolve collisions between values associated
> with the same key, as supplied to {@link Map#merge(Object, Object,
> BiFunction)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论