英文:
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::getListWithLongand 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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论