java - 具有自定义逻辑的 Java 8 Stream groupingBy
问题描述
我有一个清单Records
。其中有两个字段:LocalDateTime instant
和一个Double data
.
我想按小时对所有记录进行分组并创建一个Map<Integer, Double>
. 其中键(整数)是小时,值(双精度)是该小时的最后一个数据 - 该小时的第一个数据。
到目前为止我所做的如下:
Function<Record, Integer> keyFunc = rec->rec.getInstant().getHour();
Map<Integer, List<Record>> valueMap = records.stream().collect(Collectors.groupingBy(keyFunc));
我希望值图保持不变Double
,而不是List<Records>
.
例如:列表记录可以如下:
Instant Data
01:01:24 23.7
01:02:34 24.2
01:05:23 30.2
...
01:59:27 50.2
02:03:23 54.4
02:04:23 56.3
...
02:58:23 70.3
...
ETC
生成的地图应该是:
Key Value
1 26.5 (50.2-23.7)
2 15.9 (70.3-54.4)
...
解决方案
您主要是Collectors.mapping
在groupingBy
.
Map<Integer, List<Double>> valueMap = records.stream()
.collect(Collectors.groupingBy(keyFunc,
Collectors.mapping(Record::getData, Collectors.toList())));
这会将Record
s 按他们instant
的小时和这些记录的相应数据分组到List
地图的值中。根据进一步的评论
我想从最后一个数据中减去第一个数据
是的,列表将根据即时排序列表
您可以使用分组映射来获得所需的输出:
Map<Integer, Double> output = new HashMap<>();
valueMap.forEach((k, v) -> output.put(k, v.get(v.size() - 1) - v.get(0)));
或者,您可以使用Collectors.mapping
withCollectors.collectingAndThen
进一步作为:
Map<Integer, Double> valueMap = records.stream()
.collect(Collectors.groupingBy(keyFunc,
Collectors.mapping(Record::getData,
Collectors.collectingAndThen(
Collectors.toList(), recs -> recs.get(recs.size() - 1) - recs.get(0)))));
推荐阅读
- c# - 如何在 C# 中批量移动文件
- ruby-on-rails - Rails 6:如何在 collection_check_boxes 中要求至少一个复选框
- java - 龙目岛和泛化
- java - 正则表达式区分大写和小写字母
- angular - 在输入组件中传递翻译值
- mysql - MySql Error code: 1093- You can't specify target table 'n1' for update in FROM clause
- python - 切换程序时如何使未停靠的QDockWidget保持可见?
- vb.net - 应用程序从 Global.System.Configuration.DefaultSettingValueAttribute 而不是 app.config 获取连接字符串
- vue.js - Vuetify - 防止 v-list-item-group 取消选择
- json - 控制字符错误,可能编码不正确