简体   繁体   中英

Java 8 Lambda Stream forEach with two if-statements

I'm trying to refactoring some for-loops into lambda expressions, most of them are working fine, but I'm struggling with for-loops that contains two if-statements.

Code

        for (B2KTransactionDTO b2kTransactionDTO : result) {
            //Generate loyaltyMatchId based on transaction input
            String loyaltyMatchId = getLoyaltyMatchIdBasedOnTransactionDTO(b2kTransactionDTO);
            if (loyaltyMatchIdAmountMap.containsKey(loyaltyMatchId)) {
                BigDecimal cashback = loyaltyMatchIdAmountMap.get(loyaltyMatchId);
                b2kTransactionDTO.addLoyaltyPoints(cashback);
            }

            String loyaltyMatchInsuranceId = getLoyaltyMatchInsuranceIdBasedOnTransactionDTO(b2kTransactionDTO);
            if (loyaltyMatchInsuranceIdAmountMap.containsKey(loyaltyMatchInsuranceId)) {
                BigDecimal cashback = loyaltyMatchInsuranceIdAmountMap.get(loyaltyMatchInsuranceId);
                b2kTransactionDTO.addLoyaltyPoints(cashback);
            }
        }

I refactored this to the following code:

        result.forEach(b2kTransactionDTO -> {
            //Generate loyaltyMatchId based on transaction input
            String loyaltyMatchId = getLoyaltyMatchIdBasedOnTransactionDTO(b2kTransactionDTO);
            if (loyaltyMatchIdAmountMap.containsKey(loyaltyMatchId)) {
                BigDecimal cashback = loyaltyMatchIdAmountMap.get(loyaltyMatchId);
                b2kTransactionDTO.addLoyaltyPoints(cashback);
            }

            String loyaltyMatchInsuranceId = getLoyaltyMatchInsuranceIdBasedOnTransactionDTO(b2kTransactionDTO);
            if (loyaltyMatchInsuranceIdAmountMap.containsKey(loyaltyMatchInsuranceId)) {
                BigDecimal cashback = loyaltyMatchInsuranceIdAmountMap.get(loyaltyMatchInsuranceId);
                b2kTransactionDTO.addLoyaltyPoints(cashback);
            }
        });

Is it possible to even futher lambda-nize this?

Thanks

This is not the answer you are looking for.

I would say, don't use lambda's here.

Lambda's can help you to utilise parralelism features of cpu's to speed up processing of large datasets.

In my experience it's not worth the hassle of utilising a lambda with smaller datasets(<10(0).000);

Keep your code readable and maintainable and pluggable.

Learn to make objects that handle purposes. Don't put all the things in one object and end up with veryLongVariableNamesThatDescribeAPurpose.

When long variable names occur it should be a signal to you that you can refactor that code into several objects that handle a single purpose.

If you really want to use lambda's try the following: Seperate objects for value holders and processors and methods for seperate tasks, it will be easier in to utilise lambda's when needed because you can simply plug in the methods for the tasks required and pass on the value holder objects to get your desired results.

So, not the answer you're looking for, but this was too long really to explain in a comment.

I think you also should consider refactor your code because it looks like there's a lot of duplication between the match and matchInsurance stuff.

private static void addLoyaltyPoints(Collection<B2KTransactionDTO> result, Map<String, BigDecimal> ids, Function<B2KTransactionDTO, String> extractId)
{
    result.stream()
          .filter(b -> ids.containsKey(extractId.apply(b)))
          .forEach(b -> b.addLoyaltyPoints(ids.get(extractId.apply(b))));
}

Then the whole code you posted could become:

addLoyaltyPoints(result, loyaltyMatchIdAmountMap, Use::getLoyaltyMatchIdBasedOnTransactionDTO);
addLoyaltyPoints(result, loyaltyMatchInsuranceIdAmountMap, Use::getLoyaltyMatchInsuranceIdBasedOnTransactionDTO);

Edit: another version of addLoyaltyPoints (more concise, less expressive):

private static void addLoyaltyPoints(Collection<B2KTransactionDTO> result, Map<String, BigDecimal> ids, Function<B2KTransactionDTO, String> extractId)
{
    result.stream()
          .forEach(b -> b.addLoyaltyPoints(ids.getOrDefault(extractId.apply(b), new BigDecimal(0))));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM