Search code examples
javalambdajava-8java-stream

Converting a java for loop to stream is asking to handle exception again


I have a for loop as below which is working fine.

try {
    Accountant accountant = getAccountant(employees);
    for (Employee person : employees) {
        accountant.pay(person, this); // throws BudgetIsOverException
    }
    allSalariesPaid = true;
}
catch (BudgetIsOverException e){
    allSalariesPaid = false;
}

But when I use a stream API instead, it asks me to handle the BudgetIsOverException and shows an error at accountant.pay even though it is properly caught after the try statement. Below the code:

try {
    Accountant accountant = getAccountant(employees);
    employees.stream()
             .forEach(e->accountant.pay(e,this)); // throws BudgetIsOverException
    allSalariesPaid = true;
}
catch (BudgetIsOverException e) {
    allSalariesPaid = false;
}

My question is why is stream API expecting an exception to be caught inside the foreach block?


Solution

  • The foreach construct expects a consumer object

    void forEach(Consumer<? super T> action);

    The abstract method of consumer is

    void accept(T t);

    Note the above abstract method of consumer does not throw any checked exception so you need to handle it for each employee object unlike in above foreach loop. You could just handle and rethrow runtime exception.Its not a recommended way but the above code implies you are good to exit as soon as one of the employee's pay fail so we could go ahead with it.

        private void method() {
            try {
            Accountant accountant = getAccountant(employees);
            employees.stream()
                    .forEach(emp -> paySalary(accountant, emp, this));
            allSalariesPaid = true;
            }catch(RuntimeException e){
                allSalariesPaid = false;
            }
        }
    
        private void paySalary(Accountant accountant, Employee emp, CurrentClass currentClassRef) {
            try {
                accountant.pay(emp, currentClassRef);
            } catch (BudgetIsOverException exception) {
                throw new RuntimeException(exception);
            }
        }