42

Is it possible to transform this code to a Java 8 Optional one-line expression?

long lastPollTime;
if (object != null) {
    lastPollTime = object.getTime();
} else {
    lastPollTime = 0;
}

i.e. if some object is not null, I need to call an object method and return its result, or else return 0. Optional.ofNullable().orElse() is not suitable, as it returns the object of the same type, but i need the result of the method call or some default value.

8
  • 3
    To paraphrase Jamie Zawinski: "Some people, when faced with a problem, think 'I know, I'll use <new language feature>'; now they've got two problems". Using anything more than a conditional operator to make this into a one-liner is simply doing unnecessary work. Commented Jan 13, 2017 at 10:04
  • 1
    I would agree with Andy if you have to construct the optional first it does not really help you anything. If you however have/store the optional for other reasons the map/orElse is nice. Commented Jan 13, 2017 at 10:05
  • 1
    @mv200580 Sounds like you need to learn about the ternary operator -- alvinalexander.com/java/edu/pj/pj010018 Commented Jan 13, 2017 at 10:17
  • 1
    @mv200580 If your checkstyle config is preventing you from writing the "right" code, you should change your checkstyle rules, or use annotations to temporarily disable that check where appropriate. Discuss it with whoever holds the reins. Commented Jan 13, 2017 at 10:33
  • 1
    coderanch.com/t/376473/java/Avoid-inline-conditionals Commented Jan 13, 2017 at 10:34

6 Answers 6

105

A few forms:

long lastPollTime = Optional.ofNullable(object).map(o -> o.getTime()).orElse(0L);

long lastPollTime = Optional.ofNullable(object).map(YouObjectClass::getTime).orElse(0L);

long lastPollTime = Optional.ofNullable(object).isPresent() ? object.getTime() : 0;

long lastPollTime = object != null ? object.getTime() : 0;

Of these, the last one, which doesn't use Optional (and therefore doesn't strictly answer your question!) is simpler to read and has fewer runtime overheads, and so should be preferred.

Arguably, it's even simpler if you reverse the options:

long lastPollTime = object == null ? 0 : object.getTime();

... although you might prefer to have the default last -- it's a matter of personal taste.


If you really can't use ternary operators, and you're doing this a lot, you could write your own utility method:

public <T,U> U mapWithFallback(T obj, Function<T,U> function, U fallback) {
    if(obj == null) {
        return fallback;
    } else {
        return function.apply(obj);
    }
}

... callable as:

long lastPollTime = mapWithFallback(object, o -> o.getTime(), 0);

... or make a complete mockery of your no-ternaries check using:

public <T,U> U ifElse( Supplier<Boolean> a, Supplier<U> ifTrue, Supplier<U> ifFalse) {
     if(a.get()) {
          return ifTrue.get();
     } else {
          return ifFalse.get();
     }
}

long lastPollTime = ifElse( () -> object == null, () -> object.getTime(), () -> 0);

It's in even better taste to avoid null references altogether, so that this kind of check isn't needed -- for example using the Null Object pattern.

... or by writing methods that return Optional rather than potential nulls. Optional is a great class; use it. Just don't convert something to Optional purely so you can immediately check whether it's empty.

Sign up to request clarification or add additional context in comments.

4 Comments

has fewer runtime overheads, and so should be preferred Strongly disagree. You shouldn't bother making such "overhead reductions" until you've identified it as a problem. So, so, so often people avoid these structures for "performance reasons" when they have literally 0 measurable impact on code performance. Then when it comes time to maintain the code and add new functionality, instead of having convenient hooks to add new functionality, you're left with steaming piles of ternary logic.
@corsoKa but you omitted "simpler to read" from your quote. Premature optimisation is bad. But over-ornate constructs just for the sake of it are also bad.
Note - the Javascript library Ramda, and other FP libraries, has an ifElse(predicate, function, function) very like the one described here.
mapwithFallback() method is so sensible.
14
long lastPollTime = Optional.ofNullable(object).map(YouObjectClass::getTime).orElse(0L);

Comments

8
long lastPollTime = Optional.ofNullable(object).map(o -> o.getTime()).orElse(0L);

Instead of o -> o.getTime() you could use a methods reference like ClassOfObject::getTime

Comments

5
long lastPollTime = (object != null) ? object.getTime() : 0;

3 Comments

Yes, this is obvious decision, but in this case needs "java optional way" variant.
I don't see any Optional in this expression :) I understand that this is the shortest and likely the most effective way, but in my case it is unacceptable, unfortunately
@mv200580 my bad, i didn't get it properly, but my answer might be helpful for someone else.
3

You can do like below with java 8

long lastPollTime = 
    Optional.ofNullable(object).isPresent() ? object.getTime() : 0;

or without using java8 like this

 long lastPollTime = (object != null) ? object.getTime() : 0;

1 Comment

java 8 has boolean isPresent() method which Returns true if there is a value present, otherwise false.
1

Re ternary vs optional, if you ever needed to nest them the optional ends up being easier to read

long lastPollTime = Optional.ofNullable(object1)
  .map(o -> o.getTime())
  .orElse(Optional.ofNullable(object2)
    .map(o -> o.getTime())
    .orElse(0));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.