I have a list of Records
. Which has two fields: LocalDateTime instant
and a Double data
.
I want to groupBy all the records by Hour and create a Map<Integer, Double>
. Where the keys (Integer) are hours and values(Double) are last Data of that hour - first Data of that hour.
What I have done so far is following:
Function<Record, Integer> keyFunc = rec->rec.getInstant().getHour();
Map<Integer, List<Record>> valueMap = records.stream().collect(Collectors.groupingBy(keyFunc));
I want the value map to hold Double
instead of List<Records>
.
For Example: List records can be following:
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
Resulting map should be:
Key Value
1 26.5 (50.2-23.7)
2 15.9 (70.3-54.4)
...
You are mostly looking for Collectors.mapping
within the groupingBy
.
Map<Integer, List<Double>> valueMap = records.stream()
.collect(Collectors.groupingBy(keyFunc,
Collectors.mapping(Record::getData, Collectors.toList())));
This would group Record
s by their instant
's hour and corresponding data for such records into a List
as values of the map. Based on comments further
I want to subtract the first data from the last data
Yes the list will be sorted list based on instant
you can use the grouped map to get the desired output as:
Map<Integer, Double> output = new HashMap<>();
valueMap.forEach((k, v) -> output.put(k, v.get(v.size() - 1) - v.get(0)));
Alternatively, you could use Collectors.mapping
with Collectors.collectingAndThen
further as:
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)))));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With