Estoy tratando de encontrar la manera de calcular el porcentaje de un valor específico en una lista cuando se utiliza stream
.
Mi objeto getTag
puede tener valor G
o Y
y quiero calcular el porcentaje de G:s
la lista. El otro objeto es getDateTime
que es de la forma 1946-01-12
.
Tengo la condición filter(weather -> !weather.getDateTime().isAfter(dateTo) && !weather.getDateTime().isBefore(dateFrom))
porque yo sólo quiero el porcentaje entre dos fechas que son la entrada del usuario.
Así que cada valor DateTime corresponde a cualquiera G
o Y
. He utilizado Collectors.counting()
para calcular la frecuencia de ambos G
y Y
, pero ¿cómo puedo obtener el porcentaje?
Map<String, Long> percentage = weatherData.stream()
.filter(weather -> !weather.getDateTime().isAfter(dateTo) && !weather.getDateTime().isBefore(dateFrom))
.collect(Collectors.groupingBy(Weather::getTag, Collectors.counting()));
Si asigna el elemento que se preocupan por ( "G") a 1, y todo lo demás a 0, el valor promedio es el porcentaje de "G" en la corriente.
double pctG = list.stream()
.mapToInt(obj -> obj.getTag().equals("G") ? 1 : 0)
.summaryStatistics()
.getAverage();
Si realmente desea particionar el mapa en "G" y cubos "Y" como se muestra en la cuestión, utilizar collectingAndThen()
para modificar el resultado aguas abajo. He aquí un método de propósito general para crear una Collector
para que:
static <T> Collector<T, ?, Double> scaling(long factor) {
return Collectors.collectingAndThen(
Collectors.counting(), count -> (double) count / factor);
}
Utilizar de esta manera:
Map<String, Double> fractions = weatherData.stream()
.filter(...)
.collect(
Collectors.groupingBy(Weather::getTag, scaling(weatherData.size())));