Tengo una lista de Records
. Que tiene dos campos: LocalDateTime instant
y Double data
.
Quiero GroupBy todos los registros de horas y crear una Map<Integer, Double>
. Cuando las teclas (entero) son horas y valores (Doble) son los últimos datos de esa hora - primeros datos de esa hora.
Lo que he hecho hasta ahora es lo siguiente:
Function<Record, Integer> keyFunc = rec->rec.getInstant().getHour();
Map<Integer, List<Record>> valueMap = records.stream().collect(Collectors.groupingBy(keyFunc));
Quiero que el mapa de valor para mantener Double
en lugar de List<Records>
.
Por ejemplo: los registros de listas pueden tener lo siguiente:
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.
Resultando mapa debe ser:
Key Value
1 26.5 (50.2-23.7)
2 15.9 (70.3-54.4)
...
Usted está buscando en su mayoría Collectors.mapping
dentro de la groupingBy
.
Map<Integer, List<Double>> valueMap = records.stream()
.collect(Collectors.groupingBy(keyFunc,
Collectors.mapping(Record::getData, Collectors.toList())));
Esto haría grupo Record
s por su instant
hora 's y los datos para los registros correspondientes en una List
como valores del mapa. Sobre la base de los comentarios más
Quiero restar los primeros datos de la última de datos
Si la lista se ordena la lista basada en instantánea
se puede utilizar el mapa agrupado para obtener la salida deseada:
Map<Integer, Double> output = new HashMap<>();
valueMap.forEach((k, v) -> output.put(k, v.get(v.size() - 1) - v.get(0)));
Alternativamente, se puede utilizar Collectors.mapping
con Collectors.collectingAndThen
más ampliamente como:
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)))));