Java 8 introduces a new default method on the List
interface to sort it. It's signature is :
void sort(Comparator<? super E> c)
The documentation says:
If the specified comparator is null then all elements in this list must implement the Comparable interface and the elements' natural ordering should be used.
So if you want to sort the list by it's natural order (and that your elements are comparable) you have to do list.sort(null);
which is kind of weird of my opinion.
If they used an Optional
the doc would stated that you can optionally provide a comparator, and that if it's not provided it will assume the elements are already comparable.
A list.sort(null);
call would be transformed into list.sort(Optional.empty());
.
As it's a method that it exposed to the outside world, I would find it more accurate.
Why didn't they used the new Optional API instead?
In a nutshell, the Optional class includes methods to explicitly deal with the cases where a value is present or absent. However, the advantage compared to null references is that the Optional class forces you to think about the case when the value is not present.
Optional is a container object which may or may not contain a non-null value. You must import java. util package to use this class. If a value is present, isPresent() will return true and get() will return the value.
Java's Arrays. sort method uses quicksort, insertion sort and mergesort. There is even both a single and dual pivot quicksort implemented in the OpenJDK code.
Optional is intended to be used as a return type. That has always been the mantra of the JDK-8 developers. So they won't break their own rule by using it as an argument.
That said, I would have made the argument mandatory, and thus force the developer to use
list.sort(Comparator.<Foo>naturalOrder());
Even if I can pass null, I find the above more readable, and not much more verbose. So that's what I use in my code.
The default method is delegating to Arrays#sort
, which has existed since at least Java 1.7.
Here's the relevant snippet for the default method:
@SuppressWarnings({"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
Observe that it's converting the list into an array and letting Arrays#sort
handle it from there. The default behavior for this then would fall back to what is supported for that method.
There are two reasons why I see this being preferable to adding an Optional
:
If you don't have a Comparator
to use, or just want the "default" behavior, you can provide a null
to it. In this context, null
and Optional.isPresent()
serve the same purpose and would not earn any usability points.
It is an annoyance to have to provide null
to a function for its default behavior; better design might have been to either overload the method or allow a default naturalOrder
instance to be passed in instead.
The Optional
pattern is more meant to guard against inadvertently handling a null
reference, as opposed to being used for a null
check. The overhead in adding Optional
where a simple null
check would suffice would far outweigh its benefits, especially considering that there is no semantic difference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With