Lets first consider this example:
public class <X> Example {
public List<X> getValues() {
if (...) {
return null;
} else {
return /* a non-empty list */
}
}
public List<X> getValuesAgain() {
if (...) {
return Collections.emptyList();
} else {
return /* a non-empty list */
}
}
}
Which of those ways of returning no values is better?
I would argue that the better way is (nearly always) the way that getValuesAgain
does it; i.e. by returning an empty list. Consider the following.
With the first version, I need to test for a null
before using the result:
List<String> l = example.getValues();
if (l != null) {
for (s String: l) {
/* do something */
}
}
With the second version, I can use the result directly:
List<String> l = example.getValuesAgain();
for (s String: l) {
/* do something */
}
In short, returning null
makes life more complicated for the caller compared with returning an empty list. In theory, you may have saved the creation of an empty list object ... except that the javadoc for emptyList()
states that it doesn't need to return a distinct list object each time. (And it typically won't!)
Now consider what Optional<List<String>>
means: either a List<String>
or no value. But as we have already seen, returning an empty list is simpler for the caller that returning a null
. And the same logic applies here too.
So if getValues
returns an Optional<List<X>>
, we would need to use it like this:
Optional<List<String>> l = example.getValues();
if (l.isPresent()) {
for (s String: l.get()) {
/* do something */
}
}
Compare with the original getValuesAgain
:
List<String> l = example.getValuesAgain();
for (s String: l) {
/* do something */
}
In short, using Optional
to return a list or null
is not an improvement.
The only scenario where I think you should contemplate using Optional<List<?>>
as a return type is if the API needs to make a semantic distinction between an empty list versus no list.
The same applies for other collection types, and also for arrays, strings and other examples.
Another way of thinking about this is that the designers' intention for Optional
is to provide a way to indicate there is "no result"; see Brian Goetz's answer to this question. But we don't need to indicate there is "no result" here since we can return an empty collection.