如何使用Double数据类型减少流

时间:2019-10-12 14:30:42

标签: java lambda java-8 java-stream

我有一个ArrayList位用户定义的对象employee为

class Employee {
    String name;
    Double age;
    Double salary
}

我正在尝试通过以下代码将以上列表简化为流

Double totalSalary = empList.stream().parallel().filter(x-> x.getname().equalsIgnoreCase("XYZ")).reduce(0,(subTotal, sal)-> subTotal + dp.getSalary(), DoubleExpression::add);

这不能编译并给出错误。我该如何实现自己的目标?

2 个答案:

答案 0 :(得分:6)

首先,您必须map将Employee对象转换为双倍薪水。然后,只有您可以执行还原步骤。此外,归约步骤采用一个标识元素和一个二元运算符。但是您在那里传递了三个论点,这也是有缺陷的。

double totalSalary = empList.stream()
    .filter(x -> x.getName().equalsIgnoreCase("XYZ"))
    .mapToDouble(Employee::getSalary)
    .sum();

这是等效的减少量。请注意,0是此缩减的标识元素。

double totalSalary = empList.stream()
    .filter(x -> x.getName().equalsIgnoreCase("XYZ"))
    .mapToDouble(Employee::getSalary)
    .reduce(0, Double::sum);

答案 1 :(得分:2)

Ravindra's answer提供了正确的解决方案,但是要详细了解为什么您的解决方案不起作用,请考虑以下事项:

Double totalSalary = empList.stream().parallel()
        .filter(x -> x.getName().equalsIgnoreCase("XYZ"))
        // crucial aspect of mapping to the type that you want to reduce
        .map(Employee::getSalary)
        // reduction as a stage of stream pipeline execution
        .reduce(0,  // identity element for sum, but with a flaw!!
                (subTotal, sal) -> Double.sum(subTotal, sal), // accumulator to sum double values
                Double::sum // the combiner function compatible with accumulation
               );

身份存在缺陷的原因在于,由于0,累加器中subTotal的类型不会像double方法所预期的那样被推断为Double#sum。因此,使用Double.NaN进一步更新代码将使其工作如下:

Double totalSalary = empList.stream().parallel()
        .filter(x -> x.getName().equalsIgnoreCase("XYZ"))
        .map(Employee::getSalary)
        .reduce(Double.NaN, Double::sum, Double::sum); // identity element and method reference for accumulator

不过请注意,在这种情况下,可以将合并器排除在外而简单地表示为:

Double totalSalary = empList.stream().parallel()
        .filter(x -> x.getName().equalsIgnoreCase("XYZ"))
        .map(Employee::getSalary)
        .reduce(Double.NaN, Double::sum);

,并且由于sum最终是原始类型的操作,因此使用DoubleStream映射(将流的原始特化用于双精度)将非常方便有价值的元素。