Рассчитать процент стоимости с использованием потока - PullRequest
1 голос
/ 13 марта 2020

Я пытаюсь выяснить, как рассчитать процент от указанного значения c в списке при использовании stream.

Мой объект getTag может принимать значение G или Y, и я хочу вычислить процент G:s в списке. Другой объект - getDateTime, который имеет форму 1946-01-12.

У меня есть условие filter(weather -> !weather.getDateTime().isAfter(dateTo) && !weather.getDateTime().isBefore(dateFrom)), потому что я хочу только процент между двумя датами, которые вводятся пользователем.

Таким образом, каждое значение DateTime соответствует либо G, либо Y. Я использовал Collectors.counting() для вычисления частоты как G, так и Y, но как я могу получить процент?

Map<String, Long> percentage = weatherData.stream()
        .filter(weather -> !weather.getDateTime().isAfter(dateTo) && !weather.getDateTime().isBefore(dateFrom))
        .collect(Collectors.groupingBy(Weather::getTag, Collectors.counting()));

1 Ответ

1 голос
/ 13 марта 2020

Если вы сопоставляете интересующий вас элемент («G») с 1, а все остальное с 0, среднее значение представляет собой процент «G» в потоке.

double pctG = list.stream()
    .mapToInt(obj -> obj.getTag().equals("G") ? 1 : 0)
    .summaryStatistics()
    .getAverage();

С Java 13, вы можете использовать коллектор teeing() для подсчета элементов по тегам, и общее количество элементов после фильтрации, заканчивая делением количества групп на общее количество:

Map<String, Double> fractions = weatherData.stream()
        .filter(...)
        .collect(
            Collectors.teeing(
                Collectors.groupingBy(Weather::getTag, Collectors.counting()),
                Collectors.counting(),
                YourClass::scale));

Где функция scale() делит каждую группу на общую сумму:

static <T> Map<T, Double> scale(Map<? extends T, Long> counts, long total) {
    return counts.entrySet().stream().
        .collect(Collectors.toMap(e -> e.getKey(), ((double) e.getValue()) / total));
}
...