Java Lambda Stream group By和求和整数值/平均值

时间:2019-01-29 21:38:20

标签: java lambda

我有一个“客户对象列表”列表(客户:int id,bool isActive,int billingCount等),并且想要billingCount的总和和平均值。不幸的是,我的代码无法正常工作。我该如何更改代码才能正常工作?

总和和平均灵魂看起来像这样:

true 1234

错误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 :(得分:2)

通过您的map呼叫,您正在将Stream<Customer>转换为Stream<Boolean>,或者说是关于活跃和不活跃客户的真假流。您无法通过布尔值调用客户的getBillingCount

您可以使用the partitioningBy Collector来按布尔值分组,而无需先前的map调用。下游收集器可以是summarizingInt Collector,用于同时收集总和和平均值(以及一些您可能不需要的其他数目:计数,最大值,最小值)。

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

这将使您在一条语句中获得truefalse的统计信息。

答案 1 :(得分:1)

您真的需要活动和不活动的地图吗?那简单吗:

List(List(2, 2, 2, 3, 4, 7))
List(List(2, 3, 4, 7))
List(List(2, 3, 4, 7), List(2, 3, 5, 7))

通过将过滤器替换为def query sql = [some sql] Component.find_by_sql(sql) end

,您可以对非活动状态执行相同的操作

答案 2 :(得分:1)

您不需要使用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}