Как уменьшить потоки с двойным типом данных - PullRequest
3 голосов
/ 12 октября 2019

У меня есть ArrayList определенного пользователем объекта сотрудника как

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);

Thisне компилируется и выдает ошибку. Как мне достичь желаемой цели?

Ответы [ 2 ]

6 голосов
/ 12 октября 2019

Сначала вы должны 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);
2 голосов
/ 12 октября 2019

Ответ Равиндры предоставляет правильное решение, но чтобы понять, почему ваше решение не работает, рассмотрите следующие:

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, которое является примитивной специализацией потока для элементов с двойным значением.

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