java - 如何使用 Java 8 进行分组和收集?
问题描述
我有一个元素列表,我们称之为“关键字”,如下所示:
public class Keyword {
Long id;
String name;
String owner;
Date createdTime;
Double price;
Date metricDay;
Long position;
}
问题是每一天都有一个关键字。例如:
Keyword{id=1, name="kw1", owner="Josh", createdTime="12/12/1992", price="0.1", metricDay="11/11/1999", position=109}
Keyword{id=1, name="kw1", owner="Josh", createdTime="12/12/1992", price="0.3", metricDay="12/11/1999", position=108}
Keyword{id=1, name="kw1", owner="Josh", createdTime="12/12/1992", price="0.2", metricDay="13/11/1999", position=99}
Keyword{id=2, name="kw2", owner="Josh", createdTime="13/12/1992", price="0.6", metricDay="13/11/1999", position=5}
Keyword{id=2, name="kw2", owner="Josh", createdTime="13/12/1992", price="0.1", metricDay="14/11/1999", position=4}
Keyword{id=3, name="kw3", owner="Josh", createdTime="13/12/1992", price="0.1", metricDay="13/11/1999", position=8}
然后,从这个列表中,我想创建一个新列表,其中包含所有不同日子的所有指标在一个列表中。首先,我创建了一个这样的类:
public class KeywordMetric {
Double price;
Date metricDay;
Long position;
}
我想要归档的是从第一个列表到这样的结构:
public class KeywordMeged {
Long id;
String name;
String owner;
List<KeywordMetric> metricList;
}
我期望的例子:
KeywordMerged{id=1, name="kw1", owner="Josh", createdTime="12/12/1992", metricList=[KeywordMetric{price=0.1,metricDay="11/11/1999",position=109},KeywordMetric{price=0.3,metricDay="12/11/1999",position=108},KeywordMetric{price=0.2,metricDay="13/11/1999",position=99}]
KeywordMerged{id=2, name="kw2", owner="Josh", createdTime="13/12/1992", metricList=[KeywordMetric{price=0.6,metricDay="13/11/1999",position=5},KeywordMetric{price=0.1,metricDay="14/11/1999",position=4}]
KeywordMerged{id=3, name="kw3", owner="Josh", createdTime="13/12/1992", metricList=[KeywordMetric{price=0.1,metricDay="13/11/1999",position=8}]
我知道如何使用大量循环和可变变量来做到这一点,但我无法弄清楚如何使用流和 lambda 操作来做到这一点。我可以按 ID 对所有相关关键字进行分组:
Map<Long, List<Keyword>> kwL = kwList.stream()
.collect(groupingBy(Keyword::getId))
而且我知道.forEach()
我可以迭代该 Map,但无法弄清楚如何使collect()
流的方法从 List 传递到 KeywordMerged。
解决方案
略有不同的方法。首先,您收集按 id 分组的关键字 Map:
Map<Integer, List<Keyword>> groupedData = keywords.stream()
.collect(Collectors.groupingBy(k -> k.getId()));
此外,您将地图转换为所需格式的列表:
List<KeywordMerged> finalData = groupedData.entrySet().stream()
.map(k -> new KeywordMerged(k.getValue().get(0).getId(),
k.getValue().stream()
.map(v -> new KeywordMetric(v.getMetricDay(), v.getPrice(), getPosition()))
.collect(Collectors.toList())))
.collect(Collectors.toList());
这将适用于分组数据,但转换地图将创建KeywordMerged
对象,该对象作为参数将接收 id(您可以自己进一步扩展)并转换为List<KeywordMetric>
先前按 ID 分组的数据。
编辑:我相信通过一些提取方法可以使它看起来更好:)