Bits of Java – Episode 25: Optional in Java
We will start this new year with an episode dedicated to optionals in Java.
What are optionals? Well, we can think of them as the Java way of expressing something that can be there, but that can also not be there: an optional indeed!
Suppose you have a method which calculates the average number of points a basketball player made during a season. It will probably look something like this:
public double getAverage(List<Integer> pointsList) {
double average = 0.;
if(pointList.isEmpty()) {
return average;
}
for(Integer point : pointsList) {
average += point;
}
return average /= pointsList.size();
}
where, every entry of pointsList
is the total number of points made by a player on each match of the season.
So, let’s suppose we call such a method before the beginning of the season. In this case our pointsList
is empty, and, as we built the method, we would get 0.0
as result. But this is the same result you would have gotten for a player who scored no point when the season is over, right? So, it seems a bit unfair with respect to the previous player, which has not scored any point just because he has not played yet!
We can modify this method to return, instead of a double
, an Optional<Double>
:
public Optional<Double> getAverage(List<Integer> pointsList) {
double average = 0.;
if(pointList.isEmpty()) {
return Optional.empty();
}
for(Integer point : pointsList) {
average += point;
}
return Optional.of(average /= pointsList.size());
}
As you can see, in this way, if there are no values in the input list we return an empty Optional
, which corresponds to the case in which we cannot actually make an average since we do not have any point. While, in case the list is not empty, but the corresponding values are all zeros, we would get an Optional
containing the actual value of zero, since an average in this case was possible.
You have probably noticed that we created the Optional
not through a constructor, but using a factory, namely using a static
method of the Optional
class, which internally calls the constructor for us. This is a common pattern in Java.
In particular, in our case, Optional.empty()
creates an empty Optional
, while Optional.of()
creates an Optional
with the given value.
Once you get the resulting Optional
from our method, how can you determine whether there is actually a value associated with the Optional
or not? You can do that in different ways.
Optional<Double> average = getAverage(new ArrayList<Integer>());
Double v1;
//WAY 1
if(average.isPresent()) {
v1 = average.get();
}
//WAY 2
v1 = average.orElse(null);
//WAY 3
v1 = average.orElseGet(()->null);
//WAY 4
v1 = average.orElseThrow();
Let’s look over the different examples.
The first one is maybe the simplest one: it simply checks whether a value is present in the Optional
and, if so, it gets it. It requires two actions from our side, though.
The second method takes care by itself of the fact that the Optional
can be empty, and if so, it returns the value we specify as parameter, which in our case is null
.
A slight variant of this method is the orElseGet()
, which, instead of taking directly an alternative value, it takes a Supplier
of the type of the Optional
, so, in our case Double
. In our third example, we used this method to set the value of v1
to null
, in case nothing is present in the Optional
.
The fourth described way allows you to throw an Exception
whether the Optional
is empty. The thrown exception is a NoSuchElementException
. However, you can provide your own Exception
using the overloaded version of such a method, which takes as parameter a Supplier
of type Throwable
.
That’s it for today! Now you know what are Optional
in Java and how to use them!
Stay tuned for the next episode of the series!
by Ilenia Salvadori