0

Use Java 8 Optional features in the multiple null conditions

The conditions is

Optional<Payee> payee = Optional.ofNullable(paymtTrans.getPayee());
    
    if (payee.isPresent()
            && payee.get().getPayeeAcc() != null
            && payee.get().getPayeeAcc().size() > 0
            && payee.get().getPayeeAcc().get(0).getBnk() != null
            && payee.get().getPayeeAcc().get(0).getBnk().getBnkCtryCode() != null) {
        String ctryCode = payee.get().getPayeeAcc().get(0).getBnk().getBnkCtryCode();
    }

The requirement is to use Java 8 features without checking the null values!!

Need to get the ctryCode??

Kishore_2021
  • 645
  • 12
  • 38
  • 1
    Does this answer your question? [Java chaining map methods and using optional](https://stackoverflow.com/questions/69915682/java-chaining-map-methods-and-using-optional) – Chaosfire Aug 29 '23 at 16:02
  • No, it's a v basic question, not related to my problem. – Kishore_2021 Aug 29 '23 at 16:04
  • Specify exactly what is returned from your `getPayeeAcc()` call. – Basil Bourque Aug 29 '23 at 16:41
  • Of course, you could add a `public Optional getPrimaryBankCountryCode()` method to the Payee class, which make this look a lot cleaner. – VGR Aug 30 '23 at 13:02

1 Answers1

7

Just use Optional.map(mapperFunction). If mapperFunction returns null, then .map returns an empty Optional:

Optional<Payee> payee = Optional.ofNullable(paymentTransaction.getPayee());
Optional<String> mayBeCountryCode = 
    payee
        .map(Payee::getPayeeAccounts)
        .filter(banks -> banks.size() > 0)
        .map(banks -> banks.get(0))
        .map(BankHolder::getBank)
        .map(Bank::getBankCountryCode);

UPD. You can do it more elegant with taking stream of banks:

Optional<Payee> payee = Optional.ofNullable(paymentTransaction.getPayee());
Optional<String> mayBeCountryCode = 
    payee
        .map(Payee::getPayeeAccounts)
        .map(Collection::stream)
        .flatMap(Stream::findFirst)
        .map(BankHolder::getBank)
        .map(Bank::getBankCountryCode);

Then you can use mayBeCountryCode, for example, like that:

    mayBeCountryCode.ifPresent(countryCode ->
            // do whatever with a non-null string
    );

    String countryCode = mayBeCountryCode.orElse("none");
    String nullableCountryCode = mayBeCountryCode.orElse(null);
gdomo
  • 1,650
  • 1
  • 9
  • 18
  • How to get the getPayeeAccounts() and choose the first Account only?? – Kishore_2021 Aug 29 '23 at 16:03
  • 2
    According to your code, getPayeeAccounts() is a method of `Payee` class and it is called here: `.map(Payee::getPayeeAccounts)` – gdomo Aug 29 '23 at 16:09
  • 2
    Excellent Answer, clever. I would add a mention that if the programmer wants to return a string with a special signal value like “none” rather than return an `Optional`, they could add one more call ([`Optional.orElse`](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/Optional.html#orElse(T))) to the chain: `.orElse( "none" )` – Basil Bourque Aug 29 '23 at 16:32
  • Excellent and v quick – Kishore_2021 Aug 29 '23 at 16:36
  • 2
    I would change `banks->banks.size() > 0` to `banks->!banks.isEmpty()` as imho, it more describes what you are checking. – WJS Aug 29 '23 at 17:09
  • 2
    How to get the getPayeeAccounts() and choose the first Account only?? – Ans - using the findFirst() method payee.map(Payee::getPayeeAccounts).findFirst(); @Kishore_2021 – java_coder Aug 29 '23 at 18:04
  • 1
    thanks @BasilBourque , I've updated the answer – gdomo Aug 29 '23 at 21:37
  • 2
    also thanks @java_coder – gdomo Aug 29 '23 at 21:37