Reputation: 957
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
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
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
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
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
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