【问题标题】:Custom Collector Implementation for summing float java 8用于求和 float java 8 的自定义收集器实现
【发布时间】:2025-11-24 23:55:01
【问题描述】:

我正在尝试创建类似于Collectors.summingDouble() 的自定义浮动添加。

但我面临 2 个问题,我不确定如何解决。

  1. BiConsumer - 第 27 行 - void 方法不能返回值
  2. Collectors.of - Line#32 - Collector 类型中的(Supplier, BiConsumer<R,T>, BinaryOperator<R>, Collector.Characteristics...) 方法不适用于 参数(Supplier<Float[]>BiConsumer<Float,Employee>BinaryOperator<Float>) 在这里需要做什么来解决这个问题?
public class CustomCollector {


    public static void main(String[] args) {
        Employee e1=new Employee(1,"Tom",10.2f);
        Employee e2=new Employee(1,"Jack",10.4f);
        Employee e3=new Employee(1,"Harry",10.4f);
        ArrayList<Employee> lstEmployee=new ArrayList<Employee>();
        lstEmployee.add(e1);lstEmployee.add(e2);lstEmployee.add(e3);

/*  Implementation 1
 *  double totalSal=lstEmployee.stream().collect(Collectors.summingDouble(e->e.getSal()));
        System.out.println(totalSal);
*/  
        //Implementation 2
        Function<Employee,Float> fun=(e)->e.getSal();
        BiConsumer<Float,Employee> consumer=(val,e)->val+e.getSal();
        BinaryOperator<Float> operator=(val1,val2)->val1+val2;
        Supplier<Float[]> supplier=() -> new Float[2];

        float FtotalSal=lstEmployee.stream().collect(
                Collector.of(supplier,consumer,operator));
        System.out.println(FtotalSal);
    }

}

class Employee {
    int id;
    String name;
    float sal;
    // getters, setter, constructror
}

【问题讨论】:

    标签: java java-8 java-stream collectors


    【解决方案1】:

    看来,您将ReductionMutable Reduction 混淆了。

    您的函数(val, e) -&gt; val + e.getSal()(val1, val2) -&gt; val1 + val2) 适用于归约运算,但不适用于collect。供应商生成了一个长度为 2 的 Float[] 数组,根本不适合它。

    例如,您可以使用

    执行您的操作
    float f = lstEmployee.stream().reduce(
        0F,
        (val, e) -> val + e.getSal(),
        (val1, val2) -> val1 + val2);
    

    这会产生一些装箱开销,因为所有中间和都表示为 Float 对象。

    您可以使用Mutable Reduction 来避免这种情况,当您创建一个能够在没有装箱的情况下保存float 值的可变容器时,即new float[1]。然后,您必须提供接受数组参数并更改包含值的函数。由于您的预期结果是 float,而不是数组,因此您还需要一个 finisher 来生成最终结果。

    float f = lstEmployee.stream().collect(
        Collector.of(
            () -> new float[1], // a container capable of holding one float
            (floatArray,e) -> floatArray[0] += e.getSal(), // add one element to the array
            (a1, a2) -> { a1[0] += a2[0]; return a1; }, // merge two arrays
            array -> array[0]) // extracting the final result value
        );
    

    当然,这只是为了锻炼,因为您已经知道使用内置功能的更简单的解决方案。

    【讨论】:

    • 非常感谢@Holger。减少和收集对我来说是新术语。谢谢指出
    【解决方案2】:

    如果得到总和是重点。你可以试试下面的方法。

     float FtotalSal = (float) lstEmployee.stream().mapToDouble(e -> e.getSal()).sum();
    

    【讨论】:

    • 如何使用自定义收集器获得相同的结果?我已经实现并评论了建议的逻辑。用于练习目的。
    最近更新 更多