如何在 Java Stream 中将 POJO 的列表转换为 Map<String,List>?

Posted

技术标签:

【中文标题】如何在 Java Stream 中将 POJO 的列表转换为 Map<String,List>?【英文标题】:How to convert List of a POJO to Map<String,List> in Java Stream? 【发布时间】:2019-09-20 06:27:47 【问题描述】:

我想使用 Java 8 Stream API 以非静态方法将 Java POJO 列表转换为 Map。

我的折线图需要 x 轴的日期字符串值列表和 y 轴的数值列表。这是一种典型的地图格式。但是我的数据库为我返回了一个 POJO 列表。如果没有 Java 8 Stream API 的帮助,我不喜欢循环。 我已经尝试过这个 [ask(Java 8 List of Objects to Map<String, List> of values) 中的方法。但是,我面临两个问题。首先,我的 POJO MoreCustomDTO 除了 String 之外还包含 Integer。其次,当我尝试使用方法引用时,IDEA 抱怨无法从静态上下文中引用非静态方法。

POJO:

@Data
MoreCustomDTO 
    private String date;
    private Integer money;

DAO查询方式:

public List<MoreCustomDTO > getMoreCustomCount(@Param("format") String format, @Param("startTime") String startTime, @Param("endTime") String endTime);

Java 8 之前的解决方案:

List<MoreCustomCountDTO> customList = customDao.getMoreCustomCount(SqlUtils.DATE_TYPE_FORMAT[Integer.valueOf(type)],startTime,endTime);
Map<String, List> map = new HashMap();
List<String> dateList = new ArrayList<>();
List<Integer> moneyList = new ArrayList<>();
for (MoreCustomCountDTO data : customList) 
    dates.add(data.getDate());
    dailyAmounts.add(data.getMoney());

map.put("date", dateList);
map.put("money", moneyList);

失败代码段:

Map<String,List> map =
                    customList.stream()
                            .flatMap(element -> 
                                Map<String,String> um = new HashMap<>();
                                um.put("date",element.getDate());
                                um.put("money",element.getMoney());
                                return um.entrySet().stream();
                            )
                            .collect(Collectors.groupingBy(Map.Entry::getKey,
                                    Collectors.mapping(Map.Entry::getValue,
                                            Collectors.toList())));

我从我的数据库中得到一个列表。它是一个 JSON 格式的 Object 数组。

回复:


  "rows": [
    
      "date": "2019-09-01",
      "money": 0.00
    ,
    
      "date": "2019-09-02",
      "money": 0.00
    
  ]

但我想要一个(键)对多(值)映射格式。

回复:


  "map": 
    "date": [
      "2019-09-01",
      "2019-09-02"
    ],
    "money": [
      0.00,
      0.00
    ]
  

【问题讨论】:

由于您要收集到两个不同的列表,因此最好使用 for 循环,或者可能想在 JDK-12 中探索 teeing 你也可以使用来自谷歌番石榴库guava.dev/releases/20.0/api/docs/index.html?com/google/common/…的ArrayListMultimap 【参考方案1】:

老实说,我认为您最初的解决方案还可以。有时,强制使用该语言最奇特的特性来实现解决方案会导致代码不太清晰,这总是一件坏事。

话虽如此,我认为您打算做的是:

Map<Object, Object> map = Stream.of(
    new SimpleEntry<>(
      "date",
      customList.stream().map(MoreCustomDTO::getDate).collect(Collectors.toList())
    ),
    new SimpleEntry<>(
      "money",
      customList.stream().map(MoreCustomDTO::getMoney).collect(Collectors.toList())
    )
  ).collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue));

【讨论】:

【参考方案2】:

像这样使用 SimpleEntry:

Map<String, List<Object>> map= customList.stream().
                flatMap(element -> 
                        Stream.of(new AbstractMap.SimpleEntry<String, Object>("date", element.getDate()),
                                new AbstractMap.SimpleEntry<String, Object>("money", element.getMoney()))).
                collect(Collectors.groupingBy(AbstractMap.SimpleEntry::getKey, Collectors.mapping(AbstractMap.SimpleEntry::getValue, Collectors.toList())));

【讨论】:

以上是关于如何在 Java Stream 中将 POJO 的列表转换为 Map<String,List>?的主要内容,如果未能解决你的问题,请参考以下文章

在 Java 中将 Stream 转换为字符串

如何在 Retrofit 库中将 YAML 响应正文解析为 POJO?

如何在 java 中将 Int 转换为 Int[]?

如何在 Java 中将 Integer[] 转换为 int[] 数组?

Java8 - 基于POJO更新多个列表。

在 Flutter 中将 JSON 转换为类似于 android 的 POJO(对象)