Java 8 Streams带条件嵌套forEach改写:循环代码转Stream API实现
改写后的完整实现代码
import java.util.Objects; import java.util.List; import java.util.stream.Collectors; public AccountByCustomerDto getAccountDetails(int customerId, HttpServletRequest request) throws Exception { List<Accountowner> accountOwnerList = repo.getAccountOwners(customerId); List<AccountByCustomerDto.AccountDto> aDtoList = accountOwnerList.stream() // 先过滤非空的Accountowner,修正原代码先调用方法再判空的潜在空指针问题 .filter(Objects::nonNull) // 过滤账户币种为USD开头的 .filter(accountOwner -> accountOwner.getAccount1().getAccountCurrency().startsWith("USD")) // 转换为AccountDto对象 .map(accountOwner -> { Account account = accountOwner.getAccount1(); // 内层Stream处理余额列表,对应原内层循环 List<AccountByCustomerDto.BalancesDto> balanceDtoList = account.getAccountbalances().stream() .filter(Objects::nonNull) // 调整为常量在前的equals写法,避免字段为null时空指针 .filter(balance -> "Y".equals(balance.getCreditLimitIncluded())) .map(balance -> AccountByCustomerDto.BalancesDto.builder() .balanceType(balance.getBalanceType()) .baDto(null) .referenceDate(balance.getReferenceDate().toInstant() .atZone(ZoneId.systemDefault()) .toLocalDate()) .build()) // Java 8固定用Collectors.toList(),Java 16+可直接用toList() .collect(Collectors.toList()); String accountId = account.getAccountId() + ":" + account.getAccountCurrency(); return AccountByCustomerDto.AccountDto.builder() .accountId(Utility.encrypt(accountId)) .accountNumberDisplay(account.getAccountDisplay()) .balances(balanceDtoList) .accountLink(null) .build(); }) .collect(Collectors.toList()); return AccountByCustomerDto.builder().accounts(aDtoList).build(); }
逻辑说明
- 外层循环的过滤、转换逻辑完全通过Stream的
filter()、map()方法实现,和原循环逻辑一一对应 - 内层嵌套循环直接放在外层的转换逻辑中,用独立的Stream处理余额列表的过滤、转换,结构更清晰
- 所有原代码的业务规则完全保留,没有修改原有业务逻辑,仅做了语法层面的Stream改写
- 额外优化了两处潜在空指针问题:一是调整了accountOwner判空的先后顺序,二是调整了字符串equals的判断顺序,兼容性更好
- 如果
getAccount1()可能返回null,可以在过滤规则中新增.filter(accountOwner -> accountOwner.getAccount1() != null),进一步避免空指针异常
内容的提问来源于stack exchange,提问作者user2567005
相关产品推荐
相关产品推荐

