我有一个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
...
等
结果图应为:
Key Value
1 26.5 (50.2-23.7)
2 15.9 (70.3-54.4)
...
答案 0 :(得分:4)
您主要是在groupingBy
中寻找Collectors.mapping
。
Map<Integer, List<Double>> valueMap = records.stream()
.collect(Collectors.groupingBy(keyFunc,
Collectors.mapping(Record::getData, Collectors.toList())));
这会将Record
按其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
与Collectors.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)))));
答案 1 :(得分:2)
您可以将SUM(g.branchid=30)
用作collectingAndThen
的下游收集器,并使用每个组的两个极值来计算差异:
groupingBy
Map<Integer, Double> result = records.stream()
.collect(
Collectors.groupingBy(rec -> rec.getInstant().getHour(),
Collectors.collectingAndThen(
Collectors.toList(),
list -> {
//please handle the case of 1 entry only
list.sort(Comparator.comparing(Record::getInstant));
return list.get(list.size() - 1).getData()
- list.get(0).getData();
})));
将按小时对条目进行分组。如此处使用的,Collectors.groupingBy(rec -> rec.getInstant().getHour()
将按小时输入条目作为列表,并按Collectors.collectingAndThen
字段对每个此类列表进行排序,然后找出两个极端元素之间的差异。
答案 2 :(得分:1)
基于注释,该列表将根据时间戳进行排序,因此可以进行以下操作 :
Map<Integer, Double> valueMap = records.stream()
.collect(Collectors.groupingBy(rec -> rec.getInstant().getHour(),
Collectors.mapping(Record::getData,
Collectors.collectingAndThen(Collectors.toList(),recs -> recs.get(recs.size()-1) - recs.get(0)))));