uraza
uraza

Reputation: 957

Java Optional - If Else Statements

So after some reading I've seen that

if (optional.isPresent()) {
    //do smth
}

is not the preferred way to use Optional (http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html). But if I have an if-statement like this:

if (optional.isPresent()) {
    car = getCar(optional.get());
} else {
    car = new Car();
    car.setName(carName);
}

Is this the best way to do this or is there a more recommended way?

Upvotes: 28

Views: 66650

Answers (5)

Andrew.G
Andrew.G

Reputation: 476

Optional API update. You can use or() method if you want to return return an Optional describing the value, otherwise returns an Optional produced by the supplying function.

For instance

private <T> Optional<T> getSetting(Integer Id, String country) {
    return repo.findByIdAndCountry(id, country,)
         .or(() -> repo.findDefaultByCountry(country))
         .or(() -> repo.findGlobalDefault());
}

The or() method description

/**
 * If a value is present, returns an {@code Optional} describing the value,
 * otherwise returns an {@code Optional} produced by the supplying function.
 *
 * @param supplier the supplying function that produces an {@code Optional}
 *        to be returned
 * @return returns an {@code Optional} describing the value of this
 *         {@code Optional}, if a value is present, otherwise an
 *         {@code Optional} produced by the supplying function.
 * @throws NullPointerException if the supplying function is {@code null} or
 *         produces a {@code null} result
 * @since 9
 */
public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) {
    Objects.requireNonNull(supplier);
    if (isPresent()) {
        return this;
    } else {
        @SuppressWarnings("unchecked")
        Optional<T> r = (Optional<T>) supplier.get();
        return Objects.requireNonNull(r);
    }
}

Upvotes: 0

krishan
krishan

Reputation: 59

Car car = optional.ifPresentOrElse(
id -> getCar(id),
() -> {
    Car c = new Car();
    c.setName(carName);
    return c;
};

);

This doesn't seem to work since ifPresentOrElse is void method, it won't return anything

Upvotes: 0

wilmol
wilmol

Reputation: 1900

To take it further, if you have multiple if (optional.isPresent()) or if (obj != null)

You can do this:

(getN returns Optional<Car>)

return get1().map(Optional::of)
.orElseGet(() -> get2()).map(Optional::of)
.orElseGet(() -> get3()).map(Optional::of);

I.e. would be like this using if statements

Optional<Car> car = get1();
if (car.isPresent()){
  return car;
}
car = get2();
if (car.isPresent()){
  return car;
}
car = get3();
if (car.isPresent()){
  return car;
}
return Optional.empty();

Upvotes: 4

khelwood
khelwood

Reputation: 59096

If you can incorporate the name into the Car constructor, then you can write this:

car = optional.map(id -> getCar(id))
              .orElseGet(() -> new Car(carName));

If you must call the setter separately from your constructor, you would end up with something like this:

car = optional.map(id -> getCar(id))
              .orElseGet(() -> {
                  Car c = new Car();
                  c.setName(carName);
                  return c;
              });

Upvotes: 9

TheKojuEffect
TheKojuEffect

Reputation: 21081

You can use Optional as following.

Car car = optional.map(id -> getCar(id))
            .orElseGet(() -> {
                Car c = new Car();
                c.setName(carName);
                return c;
            });

Writing with if-else statement is imperative style and it requires the variable car to be declared before if-else block.

Using map in Optional is more functional style. And this approach doesn't need variable declaration beforehand and is recommended way of using Optional.

Upvotes: 55

Related Questions