как получить сумму и наименьшую дату из списка <> с помощью лямбды - PullRequest
0 голосов
/ 24 мая 2018
public class BusinessLog {

private Date logDate;
private double prize;

}

Учитывая объект BusinessLog, мне нужно иметь сумму для всех призов в List<BusinessLog> list также необходимо вернуть наименьшую дату из списка, возможно ли это с помощью лямбды,

Я могу сделатьэто с forEach наверняка, но как это сделать с лямбда,

То, что я пытался сделать до сих пор, это

    BigDecimal balance = BigDecimal.ZERO;

    if (list != null) {
        list.forEach(businessLog -> {
            balance.add(BigDecimal.valueOf(businessLog.getPrize()));
            // how to get lowest date 

        });
    }

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Решение с использованием потоковой передачи

Чтобы найти минимальную дату, вы можете сделать что-то вроде этого:

Optional<Date> minDate = list.stream().map(v -> v.logDate).min(Date::compareTo);

И рассчитать сумму:

double sum = list.stream().mapToDouble(v -> v.prize).sum();

Я бы не стал беспокоиться об «оптимизации» этого и попытках сделать это за один цикл, если только это не является серьезным узким местом в вашей системе (маловероятно).Разделение двух идей упрощает понимание и сопровождение кода.

Использование вами BigDecimal

Ваш код для выполнения balance.add(...) для BigDecimal на самом деле не будет работать так, как выВы написали это потому, что метод add в BigDecimal возвращает новый экземпляр, а не изменяет существующий.BigDecimal экземпляры являются неизменными.Вы не можете присвоить новое значение balance, потому что оно эффективно final из контекста лямбды.

Хотя идея использования BigDecimal хороша.Вам следует избегать использования double для всего, где важны точные десятичные знаки (например, деньги).Если вы измените prize на BigDecimal, вы не сможете использовать sum(), но вы можете использовать reduce() для выполнения той же функции.

BigDecimal sum = list.stream().map(v -> v.prize).reduce(BigDecimal.ZERO, BigDecimal::add);
0 голосов
/ 24 мая 2018

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

Например, следующий редуктор вычисляет статистику в одном BusinessLog объекте.Далее предполагается, что конструктор public BusinessLog(double prize, Date logDate) будет объявлен.

BusinessLog stats = 
        bl.stream()
        .reduce((log1, log2) -> new BusinessLog(
                log1.getPrize() + log2.getPrize(),
                log1.getLogDate().before(log2.getLogDate()) ?
                     log1.getLogDate() : log2.getLogDate()
            )).get();

Date lowestDate = stats.getLogDate();
double prizeSum = stats.getPrize();

Обратите внимание, что использование BusinessLog в качестве временного владельца статистики по сути является хаком.Для этого вам нужно разработать отдельный класс.

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