Reputation: 6432
How can I use the Java Optional API
to rewrite following code in a more elegant way:
first == null || second == null ? null : first + second;
The code should return null
if any of the two variables is null
or their sum elsewhere.
Upvotes: 2
Views: 6121
Reputation: 49
This is my solution using java stream
private Integer sum(Integer ...additions) {
return Arrays.stream(additions).filter(Objects::nonNull).reduce(0, Integer::sum);
}
Upvotes: 2
Reputation: 841
If you are taking in nulls and returning nulls, then using Optional
isn't very useful. You can wrap your code in Optional
, but it will look just like your normal null checking code with some extra junk hanging around. Using Optional
just to check for nulls is still just checking for nulls. If you rewrite your whole method to be fully Optional
aware, you get something like the following:
public Optional<Integer> add(Optional<Integer> first, Optional<Integer> second)
{
return first.flatMap(left -> second.map(right -> left + right))
}
Notice how, by making full use of the Optional interface, you no longer need to worry about special processing for null. Additionally, if someone calls your method, the return type is much more specific about what happens on null/empty input.
If the input is out of your control, as you indicated in the comments, you can wrap it in an Optional
using Optional.ofNullable
, and then proceed. If both your input and output return type are fixed, then as nice as Optional
is, you just don't have a good use for it.
Upvotes: 4
Reputation: 34460
If we stick to your requirement:
The code should return null if any of the two variables is null or their sum elsewhere.
Then you shouldn't use Optional
at all. It will only make your code less readable and harder to maintain.
The true power of Optional
doesn't reside in its elegance to avoid null-checks (nor in it's tempting potential to chain methods), but on its expressiveness to encapsulate either a present or an absent value. The best way to use it is as the return value of methods.
In your example, as you are saying that the method should return null
if either operand is null
, you are not taking advantage of Optional
's potential. On the other hand, if you had a method that returned Optional
(either empty or with the sum), you would be using it as expected:
public Optional<Integer> firstPlusSecond() {
Optional<Integer> a = Optional.ofNullable(first);
Optional<Integer> b = Optional.ofNullable(second);
if (!a.isPresent() || !b.isPresent()) {
return Optional.empty();
}
return Optional.of(a.get() + b.get());
}
This would in fact clearly express your intention, which is that the returned Optional
is either empty (in case one operand is null
) or holds the result of first + second
.
It would be even better if you had optional getters for both first
and second
:
public Optional<Integer> first() {
return Optional.ofNullable(first);
}
public Optional<Integer> second() {
return Optional.ofNullable(second);
}
This way, the firstPlusSecond()
method above would now turn to:
public Optional<Integer> firstPlusSecond() {
Optional<Integer> a = first();
Optional<Integer> b = second();
if (!a.isPresent() || !b.isPresent()) {
return Optional.empty();
}
return Optional.of(a.get() + b.get());
}
Which, IMO, is much better code.
Or even nicer, as suggested by @holi-java in the comments:
public Optional<Integer> firstPlusSecond() {
Optional<Integer> a = first();
Optional<Integer> b = second();
return a.isPresent() && b.isPresent() ?
Optional.of(a.get() + b.get()) :
Optional.empty();
}
Or, as again suggested by @holi-java, if you don't want to create optional getters for first
and second
, but still want to return an Optional
, you might do it as follows:
public Optional<Integer> firstPlusSecond() {
return first != null && second != null ?
Optional.of(first + second) :
Optional.empty();
}
Upvotes: 3
Reputation: 30686
I can understand maybe you start to learn how to operate the Optional
. How about this?
String result =
Optional.ofNullable(first)
// v--- the trick is use the `flatMap` here.
.flatMap(left -> Optional.ofNullable(second).map(right-> left + right))
.orElse(null);
Upvotes: 12