When using Collection.sort in Java what should I return when one of the inner objects is null
Example:
Collections.sort(list, new Comparator
if comparing two property, attr1 natural order, attr2 reverse order, and attr2 can be null:
datas.sort(comparing(Data::getAttr1, naturalOrder()).
thenComparing(Data::getAttr2, nullsLast(reverseOrder())));
In Java 8 you can also use nullsFirst()
:
Comparator.nullsFirst(Date::compareTo).compare(dateOne, dateTwo);
Or nullsLast()
:
Comparator.nullsLast(Date::compareTo).compare(dateOne, dateTwo);
These methods will either sort null
to the beginning or to the end. There is no wrong or right whether you consider null
bigger or smaller than another objects. This is totally up to you, as others stated already.
Following the answer from Nikita Rybak, i'm already have a enum comparator, and only add the null logic from here.
public enum Orden implements Comparator<CmunParametrosDTO> {
ByStrDescripcion {
public int compare(CmunParametrosDTO item1, CmunParametrosDTO item2) {
if (item1.getStrDescripcion() == null && item2.getStrDescripcion() == null)
return 0;
if (item1.getStrDescripcion() == null)
return 1;
else if (item2.getStrDescripcion() == null)
return -1;
return item1.getStrDescripcion().compareTo(item2.getStrDescripcion());
}
}
public abstract int compare(CmunParametrosDTO item1, CmunParametrosDTO item2);
public Comparator<CmunParametrosDTO> ascending() {
return this;
}
public Comparator<CmunParametrosDTO> descending() {
return Collections.reverseOrder(this);
}
}
In this form i can call the sort method on my list.
if(isBolOrdAscendente()) Collections.sort(listado, CmunParametrosDTO.Orden.ByStrDescripcion .ascending());
else Collections.sort(listado, CmunParametrosDTO.Orden.ByStrDescripcion .descending());
Naturally, it's your choice. Whatever logic you write, it will define sorting rules. So 'should' isn't really the right word here.
If you want null to appear before any other element, something like this could do
public int compare(MyBean o1, MyBean o2) {
if (o1.getDate() == null) {
return (o2.getDate() == null) ? 0 : -1;
}
if (o2.getDate() == null) {
return 1;
}
return o2.getDate().compareTo(o1.getDate());
}
It depends, do you consider null as a big value or a low value.
You can consider most of the time that null < everything else, but it depends on the context.
And 0 would be a terrible return value here.
Depending on whether the object is null, or the content of the object is null.
The object is null:
import static java.util.Comparator.*;
List<Data> listOfData = Arrays.asList(
new Data("foo"),
null,
new Data("bar"),
new Data("nyu"));
listOfData.sort(nullsFirst(comparing(Data::getValue)));
listOfData.forEach(System.out::println);
//OUTPUT:
// null
// Data(bar)
// Data(foo)
// Data(nyu)
The content of the object is null:
List<Data> listOfData = Arrays.asList(
new Data("foo"),
new Data(null),
new Data("bar"),
new Data("nyu"));
listOfData.sort(nullsFirst(
comparing(Data::getValue, nullsFirst(naturalOrder()))));
listOfData.forEach(System.out::println);
//OUTPUT:
// Data(null)
// Data(bar)
// Data(foo)
// Data(nyu)