Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Java Optional to elegantly replace Ternary operators

A super simple question:

Here's my plain Java code using traditional ternary operator ?

public DateTime getCreatedAt() {
    return !recordA.isPresent() ? recordB.get().getCreatedAt() : recordA.get().getCreatedAt();
}

My best bet is following:

public DateTime getCreatedAt() {
    return recordA.map(
        record -> record.getCreatedAt())
        .orElse(recordB.get().getCreatedAt());
  }

This could compile, but looks like it's not behaving correctly. It always executes both branches, for e.g. when recordA isPresent(), it still executes recordB.get().getCreatedAt() which throws me

java.util.NoSuchElementException: No value present

Any help is appreciated!

Basically, I'd like to replace the traditional ternary operator with more advanced Optional/lamda features.

like image 274
Fisher Coder Avatar asked Nov 08 '18 22:11

Fisher Coder


People also ask

What can I use instead of a ternary operator?

The alternative to the ternary operation is to use the && (AND) operation. Because the AND operator will short-circuit if the left-operand is falsey, it acts identically to the first part of the ternary operator.

How do you handle 3 conditions in a ternary operator?

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.


2 Answers

To avoid eagerly evaluating else-branches, use orElseGet, which takes an instance of the functional interface Supplier:

return recordA.map(
    record -> record.getCreatedAt())
    .orElseGet(() -> recordB.get().getCreatedAt());
like image 184
nanofarad Avatar answered Sep 22 '22 03:09

nanofarad


My question about recordB being Optional got unanswered but if it is Optional then you cannot just safely call its get method, you need to check if it is empty or not. Here safe call to get record or null if both recordA and recordB are empty Otionals.

        recordA
            .map(Record::getCreatedAt)
            .orElseGet( () -> recordB.map(Record::getCreatedAt).orElse(null) );
like image 36
tsolakp Avatar answered Sep 25 '22 03:09

tsolakp