I have this piece of code :
Map<String, BillingAccount> billingAccountsMap = new HashMap<>();
for (BillingAccount ba : billingAccounts) {
if (ba.getBillingAccountIdentifier() != null && ba.getBillingAccountIdentifier().getIdentifier() != null) {
billingAccountsMap.put(ba.getBillingAccountIdentifier().getIdentifier(), ba);
}
}
All I want is to rewrite it in a functional way with Java Stream API and collect(Collectors.toMap())
, but I am a bit perplexed with the null
cases.
I am using Java 11. Thanks in advance!
CodePudding user response:
Use Collectors.toMap(..)
to convert a stream of items to a map. In your case:
var billingAccountsMap = billingAccounts.stream()
.filter(ba -> ba.getBillingAccountIdentifier() != null)
.filter(ba -> ba.getBillingAccountIdentifier().getIdentifier() != null)
.collect(Collectors.toMap(ba -> ba.getBillingAccountIdentifier().getIdentifier(), ba -> ba));
See this answer for more information.
CodePudding user response:
Map<String, BillingAccount> billingAccountsMap = billingAccounts.stream()
.filter(ba -> ba.getBillingAccountIdentifier() != null
&& ba.getBillingAccountIdentifier().getIdentifier() != null)
.collect(Collectors.toMap(ba -> ba.getBillingAccountIdentifier().getIdentifier(), ba -> ba));
CodePudding user response:
You could stream your List
of BillingAccount
, then use the aggregate operation filter
to make sure that each BillingAccount
and its nested fields are not null with a short-circuited condition. Finally, collect the results where each key is the BillingAccount
's identifier while the corresponding value is the object itself.
Map<String, BillingAccount> billingAccountsMap = billingAccounts.stream()
.filter(ba -> Objects.nonNull(ba)
&& Objects.nonNull(ba.getBillingAccountIdentifier())
&& Objects.nonNull(ba.getBillingAccountIdentifier().getIdentifier()))
.collect(Collectors.toMap(ba -> ba.getBillingAccountIdentifier().getIdentifier(), Function.identity()));
CodePudding user response:
You can filter out nullable values using filter()
operation and then apply collect
by passing a built-in collector Collectors.toMap()
into it:
Map<String, BillingAccount> billingAccountsById = billingAccounts.stream()
.filter(account -> Objects.nonNull(account.getBillingAccountIdentifier()))
.filter(account -> Objects.nonNull(account.getBillingAccountIdentifier().getIdentifier()))
.collect(Collectors.toMap(
account -> account.getBillingAccountIdentifier().getIdentifier(), // keyMapper
Function.identity())); // valueMapper
Note that for this approach, every identifier has to be unique. Otherwise, you need to provide mergeFunction
as the third argument to resolve values mapped to the same key.
CodePudding user response:
You can use groupingBy
once filter
for null checks got applied:
billingAccounts.stream()
.filter(ba -> ba.getBillingAccountIdentifier() != null
&& ba.getBillingAccountIdentifier().getIdentifier() != null)
.collect(Collectors.groupingBy(x -> x.getBillingAccountIdentifier().getIdentifier()));