如果我想要列出账户的当前余额列表,我可以这样做:
accountOverview.setCurrentBalance(account.stream().
filter(a -> a.getCurrentBalance() != null).
mapToLong(a -> a.getCurrentBalance()).
sum());
Run Code Online (Sandbox Code Playgroud)
但是这个表达式将返回0,即使所有余额都为空.如果所有余额都为空,我希望它返回null,如果有非空0余额则返回0,否则返回余额之和.
我怎么能用lambda表达式做到这一点?
非常感谢
一旦你从流中过滤它们,就无法知道所有余额是否都是null(除非检查什么count()返回但是你将无法使用流,因为它是终端操作).
对数据进行两次传递可能是直接的解决方案,我可能会首先使用它:
boolean allNulls = account.stream().map(Account::getBalance).allMatch(Objects::isNull);
Long sum = allNulls ? null : account.stream().map(Account::getBalance).filter(Objects::nonNull).mapToLong(l -> l).sum();
Run Code Online (Sandbox Code Playgroud)
您可以使用您的解决方案摆脱过滤步骤reduce,尽管可读性可能不是最好的:
Long sum = account.stream()
.reduce(null, (l1, l2) -> l1 == null ? l2 :
l2 == null ? l1 : Long.valueOf(l1 + l2));
Run Code Online (Sandbox Code Playgroud)
注意这个Long.valueOf电话.这是为了避免条件表达式的类型long,因此在某些边缘情况下是NPE.
OptionalAPI.首先,Stream<Optional<Long>>从余额的价值中创建一个并减少它们:
Optional<Long> opt = account.stream()
.map(Account::getBalance)
.flatMap(l -> Stream.of(Optional.ofNullable(l)))
.reduce(Optional.empty(),
(o1, o2) -> o1.isPresent() ? o1.map(l -> l + o2.orElse(0L)) : o2);
Run Code Online (Sandbox Code Playgroud)
Optional<Long>如果所有值都是空的,这将给你一个空的null,否则它会给你非空值的总和.
或者您可能想为此创建一个自定义收集器:
class SumIntoOptional {
private boolean allNull = true;
private long sum = 0L;
public SumIntoOptional() {}
public void add(Long value) {
if(value != null) {
allNull = false;
sum += value;
}
}
public void merge(SumIntoOptional other) {
if(!other.allNull) {
allNull = false;
sum += other.sum;
}
}
public OptionalLong getSum() {
return allNull ? OptionalLong.empty() : OptionalLong.of(sum);
}
}
Run Code Online (Sandbox Code Playgroud)
然后:
OptionalLong opt = account.stream().map(Account::getBalance).collect(SumIntoOptional::new, SumIntoOptional::add, SumIntoOptional::merge).getSum();
Run Code Online (Sandbox Code Playgroud)
现在,我就这样吧。想法?
accountOverview.setCurrentBalance(account.stream().
filter(a -> a.getCurrentBalance() != null).
map(a -> a.getCurrentBalance()).
reduce(null, (i,j) -> { if (i == null) { return j; } else { return i+j; } }));
Run Code Online (Sandbox Code Playgroud)
因为我已经过滤了空值,所以我保证不会碰到任何空值。通过使初始参数减少“null”,我可以确保在空列表中返回 null。
虽然读起来有点困难/混乱。想要一个更好的解决方案..
编辑感谢 pbabcdefp,我已经采用了这个更受人尊敬的解决方案:
List<Account> filtered = account.stream().
filter(a -> a.getCurrentBalance() != null).
collect(Collectors.toList());
accountOverview.setCurrentBalance(filtered.size() == 0?null:
filtered.stream().mapToLong(a -> a.getCurrentBalance()).
sum());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10014 次 |
| 最近记录: |