Java流API-还原过程中的复杂计算

发布于 2025-02-06 08:22:53 字数 2210 浏览 1 评论 0原文

是否有一些更好的方法在减少方面进行更复杂的计算(检查getCurrentbalance):

@Override
    public Map<User, BigDecimal> getTotalExpensesForUsers(Group group) {
        return group.getExpenses().stream()
                .collect(Collectors.groupingBy(
                        Expense::getUser,
                        Collectors.reducing(BigDecimal.ZERO, Expense::getAmount, BigDecimal::add)
                ));
    }

    @Override
    public Map<User, BigDecimal> getCurrentBalance(Group group) {
        final var defaultTotalWeight = BigDecimal.valueOf(group.getDefaultTotalWeight());
        var totalExpensesPerUser = getTotalExpensesForUsers(group);
        final var averageExpensePerUser = totalExpensesPerUser.values().stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(defaultTotalWeight);

        totalExpensesPerUser.entrySet()
                .forEach(e -> e.setValue(e.getValue().subtract(averageExpensePerUser)));
        return totalExpensesPerUser;
    }

我想以某种方式将其放入一个流,因为目前我正在多次迭代集合。还是我应该使用循环的情况?

的含义

PS希望是代码自我解释 因为我得到了很多回答,即在一次迭代中不可能做到这一点,所以我正在更新这个问题。我知道不可能在一次迭代中进行操作,但是像这样,我可以用两个迭代来进行:

@Override
    public Map<User, BigDecimal> getCurrentBalanceAlternative(Group group) {
        var currentBalance = new HashMap<User, BigDecimal>();
        final var defaultTotalWeight = BigDecimal.valueOf(group.getDefaultTotalWeight());
        var totalExpense = BigDecimal.ZERO;

        for(Expense expense: group.getExpenses()){
            var expenseUser = expense.getUser();
            var expenseAmount = expense.getAmount();

            totalExpense = totalExpense.add(expenseAmount);

            currentBalance.put(expenseUser, currentBalance.getOrDefault(expenseUser, BigDecimal.ZERO).add(expenseAmount));
        }

        var averageExpensePerUser = totalExpense.divide(defaultTotalWeight);
        currentBalance.entrySet()
                .forEach(e -> e.setValue(e.getValue().subtract(averageExpensePerUser)));

        return currentBalance;
    }

但是,使用流,我必须分别计算totalexpense。

is there some me better way how to do more complicated calculation in reduction than this (check getCurrentBalance):

@Override
    public Map<User, BigDecimal> getTotalExpensesForUsers(Group group) {
        return group.getExpenses().stream()
                .collect(Collectors.groupingBy(
                        Expense::getUser,
                        Collectors.reducing(BigDecimal.ZERO, Expense::getAmount, BigDecimal::add)
                ));
    }

    @Override
    public Map<User, BigDecimal> getCurrentBalance(Group group) {
        final var defaultTotalWeight = BigDecimal.valueOf(group.getDefaultTotalWeight());
        var totalExpensesPerUser = getTotalExpensesForUsers(group);
        final var averageExpensePerUser = totalExpensesPerUser.values().stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(defaultTotalWeight);

        totalExpensesPerUser.entrySet()
                .forEach(e -> e.setValue(e.getValue().subtract(averageExpensePerUser)));
        return totalExpensesPerUser;
    }

I would like to somehow put it to one stream because currently I am iterating over the collection multiple times. Or is this case when I should use for loop instead?

P.S. hopefully is the meaning of the code self explaining if not, I will update the question

EDITED
Because I got a lot of responses that it is not possible to do it in one iteration I am updating this question. I know it is not possible to do it in one iteration, but like this I am able to do it with two:

@Override
    public Map<User, BigDecimal> getCurrentBalanceAlternative(Group group) {
        var currentBalance = new HashMap<User, BigDecimal>();
        final var defaultTotalWeight = BigDecimal.valueOf(group.getDefaultTotalWeight());
        var totalExpense = BigDecimal.ZERO;

        for(Expense expense: group.getExpenses()){
            var expenseUser = expense.getUser();
            var expenseAmount = expense.getAmount();

            totalExpense = totalExpense.add(expenseAmount);

            currentBalance.put(expenseUser, currentBalance.getOrDefault(expenseUser, BigDecimal.ZERO).add(expenseAmount));
        }

        var averageExpensePerUser = totalExpense.divide(defaultTotalWeight);
        currentBalance.entrySet()
                .forEach(e -> e.setValue(e.getValue().subtract(averageExpensePerUser)));

        return currentBalance;
    }

but with streams I had to calculate the totalExpense separately.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文