Java Lambda Stream group By и суммирование целых значений / среднего - PullRequest
0 голосов
/ 30 января 2019

У меня есть список объектов Customer (Список клиентов: int id, bool isActive, int billingCount, ...) и я хочу получить сумму и среднее значение billingCount.К сожалению, мой код не работал.Как мне нужно изменить код, чтобы он работал?

сумма и среднее значение должны выглядеть следующим образом:

true 1234

false 1234

 Map<Boolean, Integer> sum = customer.stream()
                .map(c -> c.getIsActive())
                .collect(Collectors.groupingBy(c -> c, Collectors.summingInt(Customer::getBillingCount)));


Map<Boolean, Integer> average = customer.stream()
                .map(c -> c.getIsActive())
                .collect(Collectors.groupingBy(c -> c, Collectors.averagingInt(Customer::getBillingCount)));
    }

Я получаю следующую ошибку:

Error:(146, 17) java: no suitable method found for collect(java.util.stream.Collector<Customer,capture#1 of ?,java.util.Map<java.lang.Object,java.lang.Integer>>)
    method java.util.stream.Stream.<R>collect(java.util.function.Supplier<R>,java.util.function.BiConsumer<R,? super java.lang.Boolean>,java.util.function.BiConsumer<R,R>) is not applicable
      (cannot infer type-variable(s) R
        (actual and formal argument lists differ in length))
    method java.util.stream.Stream.<R,A>collect(java.util.stream.Collector<? super java.lang.Boolean,A,R>) is not applicable
      (inference variable T has incompatible bounds
        lower bounds: java.lang.Object,Customer
        lower bounds: java.lang.Boolean)

Ответы [ 3 ]

0 голосов
/ 30 января 2019

Вам действительно нужна карта для активных и неактивных?Как насчет просто:

IntSummaryStatistics summaryActive = customer.stream()
        .filter(Customer::getIsActive)
        .mapToInt(Customer::getBillingCount)
        .summaryStatistics();

long sumActive  = summary.getSum();
double averageActive = summary.getAverage();

И вы можете сделать то же самое с неактивным, заменив фильтр на .filter(c -> !c.getIsActive())

0 голосов
/ 30 января 2019

Вам не нужно использовать map.См. Пример ниже:

List<Customer> customers = Arrays.asList(
        new Customer(10, true, 5),
        new Customer(11, true, 3),
        new Customer(20, false, 12),
        new Customer(21, false, 11));

Map<Boolean, Integer> sum = customers
        .stream()
        .collect(Collectors.groupingBy(Customer::isActive, Collectors.summingInt(Customer::getBillingCount)));
System.out.println(sum);

Map<Boolean, Double> avg = customers
        .stream()
        .collect(Collectors.groupingBy(Customer::isActive, Collectors.averagingInt(Customer::getBillingCount)));
System.out.println(avg);

Над отпечатками кода:

{false=23, true=8}
{false=11.5, true=4.0}
0 голосов
/ 30 января 2019

С вашими map звонками вы конвертируете Stream<Customer> в Stream<Boolean> или поток просто правдивых и ложных высказываний о ваших активных и неактивных клиентах.Вы не можете вызвать getBillingCount Клиента в логических значениях.

Вы можете использовать partitioningBy Collector для группировки по логическому значению без предварительного вызова map.Нижний коллектор может быть summarizingInt Collector для сбора суммы и среднего (плюс несколько других, которые вам могут не понадобиться: count, max, min) одновременно.

Map<Boolean, Integer> stats = customer.stream()
    .collect(Collectors.partitioningBy(Customer::getIsActive,
                                       Collectors.summarizingInt(Customer::getBillingCount)));

Это даст вам статистику для true и false в одном утверждении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...