【问题标题】:Return Optional<User> instead of Optional<BigDecimal> which is inside返回 Optional<User> 而不是里面的 Optional<BigDecimal>
【发布时间】:2019-07-29 17:43:43
【问题描述】:

我正在尝试编写一个返回最富有员工的流。

Optional<User> getRichestEmployee() {
    return getUserStream()
        .flatMap(user -> user.getAccounts().stream())
        .map(this::getAccountAmountInPLN)
        .sorted(Comparator.reverseOrder())
        .findFirst();
}

我的方法getAccounts() 返回List&lt;Account&gt;

我的方法getAccountAmountInPLN 是这样的:

BigDecimal getAccountAmountInPLN(final Account account) {
    return account
            .getAmount()
            .multiply(BigDecimal.valueOf(account.getCurrency().rate))
            .round(new MathContext(4, RoundingMode.HALF_UP));
}

我的问题是,getRichestEmployee() 返回Optional&lt;BigDecimal&gt;

我无法return 最富有的员工。在流上运行时,我无法访问 User 对象。如何返回用户?

【问题讨论】:

  • 要找到最富有的员工(假设User?),您不是必须将所有员工账户的金额相加吗?我认为没有尝试为员工获取总账户余额。重新考虑你想要做什么。
  • 我们可以查看您的 Account 类吗?
  • @Andreas 你是对的。所以我必须总结每个员工的所有账单。 (我不知道为什么我没有在问题中添加它 - 它是我的许多版本和这种方法尝试的结果)。 @BenjaminUrquhart @Builder @Data public class Account { private final AccountType type; private final String number; private final BigDecimal amount; private final Currency currency; }

标签: java java-8 functional-programming java-stream optional


【解决方案1】:

制作您自己的比较器,不要将每个帐户映射到其余额:

Optional<User> getRichestEmployee() {
 return getUserStream()
    .flatMap(user -> user.getAccounts().stream())
    .sorted((a1, a2) -> this.getAccountAmountInPLN(a2).compareTo(this.getAccountAmountInPLN(a1)))
    // Assuming there's a getter for the account owner...
    .map(Account::getOwner) // replace with Account's getter for owner
    .findFirst();

【讨论】:

  • Account::getOwner 从数据的角度来看是一个全新的结构,可能不会被保留。我的意思是,问题中没有任何信息可以让您获得拥有帐户的所有者。
【解决方案2】:

我假设您通过查找金额最高的帐户来计算用户的财富。

首先创建一个额外的方法来从用户那里获取金额:

public BigDecimal getUserMaxAmount(User user) {
    return user
            .getAccounts()
            .stream()
            .map(this::getAccountAmountInPLN)
            .max(Comparator.naturalOrder())
            .orElse(BigDecimal.ZERO); //if user has no account I default to 0
}

那么你可以这样使用它:

Optional<User> getRichestEmployee() {
    return getUserStream()
            .sorted(Comparator.comparing(this::getUserMaxAmount, Comparator.reverseOrder()))
            .findFirst();
}

甚至更简单:

Optional<User> getRichestEmployee() {
    return getUserStream().max(Comparator.comparing(this::getUserMaxAmount));
}

如果您的意图是通过汇总所有金额来计算用户的财富,您应该通过汇总金额将您的流减少为单个值:

public BigDecimal getUserTotalAmount(User user) { //instead of getUserMaxAmount
    return user
            .getAccounts()
            .stream()
            .map(this::getAccountAmountInPLN)
            .reduce(BigDecimal.ZERO, BigDecimal::add);

【讨论】:

  • 感谢您的想法和假设我必须通过添加所有金额来计算用户的财富。
【解决方案3】:

首先,要找到最富有的员工,您需要将员工账户的金额相加。

其次,查找总金额最大的员工,使用max(Comparator&lt;? super T&gt; comparator)

例子:

Optional<User> getRichestEmployee() {
    return getUserStream()
            .max(Comparator.comparing(this::getEmployeeAmountInPLN));
}

BigDecimal getEmployeeAmountInPLN(final User user) {
    return user.getAccounts()
            .stream()
            .map(this::getAccountAmountInPLN)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
}

BigDecimal getAccountAmountInPLN(final Account account) {
    return account
            .getAmount()
            .multiply(BigDecimal.valueOf(account.getCurrency().rate))
            .round(new MathContext(4, RoundingMode.HALF_UP));
}

【讨论】:

    猜你喜欢
    • 2019-07-20
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    • 1970-01-01
    • 2018-05-11
    • 2021-06-16
    相关资源
    最近更新 更多