Search code examples
javalambdajava-stream

Use of lambda expression in java 8


I want to refactor this code to use lambda expression java 8

for(int i = 0; i < customers.getCUSTOMER().size(); i++){
   if (customers.getCUSTOMER().get(i).getINCOME().getGROSSMONTH1().toBigInteger()
     < customers.getCUSTOMER().get(i).getINCOME().getNETTSALMONTH1().toBigInteger()){

        log.error("")
        throw new RuntimeException();
   }
}

Solution

  • You are iterating over the elements of customers.getCUSTOMER(), which appears to be a List (and I assume for the purposes of this answer that it is one). Presumably, then, you're going to process that list's stream:

    customers.getCUSTOMER().stream()
    

    you're using the getINCOME() of each element twice, and not any other aspect of it at all, so perhaps you want to map elements via that method. Supposing that the elements of the customer list are of type Customer, that might be

            .map(Customer::getINCOME)
    

    There are various ways to go from there, but since you're throwing an exception when a condition is satisfied, I'd personally go with Stream.anyMatch():

            .anyMatch(x -> x.getGROSSMONTH1().toBigInteger().compareTo(
                    x.getNETTSALMONTH1().toBigInteger()) < 0)
    

    That produces a boolean result that tells you whether any element satisfies the condition, and it stops looking as soon as it finds one that does (and the predicate for the anyMatch() is a lambda). You would use it in an if expression similar to the one you have now:

    if (customers.getCUSTOMER().stream()
            .map(Customer::getINCOME)
            .anyMatch(x -> x.getGROSSMONTH1().toBigInteger().compareTo(
                    x.getNETTSALMONTH1().toBigInteger()) < 0) {
        log.error("")
        throw new RuntimeException();
    }
    

    Since you're throwing a RuntimeException, it would also be possible to do that with a lambda, inside the stream, but that's not generally possible if you're throwing a checked exception. In the checked-exception case, something along the lines presented here is usually needful.

    On the other hand, if you want to log information about the element that failed then you would need to do that inside the stream. Additionally, in that case you might want to skip the map(). You could instead filter() based on the predicate, and findFirst() among the elements, if any, remaining (or findAny() if you don't care whether it's the first that you report on). The result is an Optional, which you can process, if present, with another lambda:

    customers.getCUSTOMER().stream()
            .filter(x -> x.getINCOME().getGROSSMONTH1().toBigInteger().compareTo(
                    x.getINCOME().getNETTSALMONTH1().toBigInteger()) < 0)
            .findFirst()
            .ifPresent(x -> {
                log.error(x.getName() + " invalid: net salary is larger than gross")
                throw new RuntimeException();
            });
    

    Note that this does not solve the checked-exception problem. You cannot throw a checked exception from inside the ifPresent lambda.