Is there a way to continue working with the result of a method call as a Stream with Functional Java?

Viewed 58

I'm fairly new to functional programming in Java, and I'm still experimenting with the code represented below.

I've created a method which for finding an Object within an Array using stream.

Method for finding an Account with provided clientIBAN:

public static Account findAccountByIBAN(String clientIBAN) {

    return bankAccounts.stream()
        .filter(account -> account.getIBAN()
            .equals(clientIBAN)).findFirst()
        .orElse(null);
}

I want to continue working with the result returned by this method.

My idea is to modify the result in the calling method. I want to know if there is a more elegant way to do that than the one I came up with?

Method that changes the state of the Account:

public static void depositToAccount(String clientIBAN, BigDecimal depositedAmount) {
    
    findAccountByIBAN(clientIBAN)
        .setAccountBalance(findAccountByIBAN(clientIBAN)
            .getAccountBalance()
            .add(depositedAmount));
}

Another option I was thinking of is just to iterate over accounts with a stream write inside depositToAccount() instead of calling findAccountByIBAN():

public static void depositToAccount(String clientIBAN, BigDecimal depositedAmount) {
    bankAccounts.stream()
        .filter(account -> account.getIBAN()
            .equals(clientIBAN)).findFirst()
        .ifPresent(balance -> 
            balance.setAccountBalance(balance.getAccountBalance().add(depositedAmount)));
}

The crux of my problem is that I want to keep iterating over that method with different things. I want to use filter() for my conditional logic instead of if-statements, but I cannot do that unless I can work with the result of my method as a stream.

1 Answers

The crux of my problem is that I want to keep iterating over that method with different things. I want to use filter() for my conditional logic instead of if-statements, but I cannot do that unless I can work with the result of my method as a stream.

It feels like you want to extend the logic by reusing the stream?

Stream is a one-time-use mean of iteration. Once it produces the result or does the final action accordingly with its terminal operation, it gets closed and can't be used any further.

You have to place all the needed logic in the stream, there's no workaround.

But stream might produce an object with effectively encapsulates several resulting values (example from the JDK - SummaryStatistics classes like IntSummaryStatistics). And you can create a custom class for such a purpose.

Also, reminder: Predicates, Functions, etc. don't necessarily have to be hard-coded, you can provide them as method parameters.


Now, a word regarding the different versions of the code you've shared.

From the perspective of clean coding, the last version of the depositToAccount() isn't very great because it mixes the responsibilities of finding the account by clientIBAN and making operation with this account. It's better to keep the separately, like in your first version, as the Single responsibility principle suggest.

And there's a couple of things which are worth to point out:

  • In the first version, you're not checking whether the result returned by findAccountByIBAN() is not null which might result in a NullPointerException.

  • As @Eritrean has mentioned in the comments, instead of returning null from findAccountByIBAN() if a result was not found, it would be better to change the return type to Optional<Account> in order to be able to leverage the Optional API.

Related