这可能是一个简单的问题,但我想清楚地理解它...
我有这样的代码:
public final class Persona
{
private final int id;
private final String name
public Persona(final int id,final String name)
{
this.id = id;
this.name = name;
}
public int getId(){return id;}
public String getName(){return name;}
@Override
public String toString(){return "Persona{" + "id=" + id + ", name=" + name+'}';}
}
我正在测试此代码:
import static java.util.Comparator.*;
private void nullsFirstTesting()
{
final Comparator<Persona>comparator = comparing(Persona::getName,nullsFirst(naturalOrder()));
final List<Persona>persons = Arrays.asList(new Persona(1,"Cristian"),new Persona(2,"Guadalupe"),new Persona(3,"Cristina"),new Persona(4,"Chinga"),new Persona(5,null));
persons
.stream()
.sorted(comparator)
.forEach(System.out::println);
}
显示以下结果:
Persona{id=5, name=null}
Persona{id=4, name=Chinga}
Persona{id=1, name=Cristian}
Persona{id=3, name=Cristina}
Persona{id=2, name=Guadalupe}
这些结果对我来说还可以,但是我有一个理解上的问题。
当我忽略
new Persona(5,null)
对象并通过比较器时:final Comparator<Persona>comparator = comparing(Persona::getName);
它像一种魅力。我的排序是通过
natural order of name property
进行的。当我用name=null
添加对象时出现问题,我只是想我需要这样的比较器。final Comparator<Persona>comparator = comparing(Persona::getName,nullsFirst());
我的想法是错误的:“好的,当名称为非空时,它们按照
natural order of name
进行排序,就像以前的比较器一样,如果它们是null
,则它们将是第一个,但是我的非空名称仍将被排序自然顺序“。但是正确的代码是这样的:
final Comparator<Persona>comparator = comparing(Persona::getName,nullsFirst(naturalOrder()));
我不了解
nullsFirst
的参数。我只是以为natural order of name
会显式[默认]甚至处理null
值。但是文档说:
这行代码:“如果两者都不为空,则使用指定的
Comparator
来确定顺序。”我对何时以及如何显式设置自然顺序或何时推断自然顺序感到困惑。
最佳答案
使用只有一个参数的comparing
时得到的“自然顺序”比较器不能处理空值。 (我不确定您的想法是从哪里来的。)Comparable
类的“自然顺序”由compareTo()
方法定义,该方法的用法如下:
obj1.compareTo(obj2)
显然,如果
obj1
为null,则此方法将无效。对于String
,如果obj2
为null,它也会引发异常。naturalOrder()
方法返回比较两个对象的Comparator
。 javadoc明确表示该比较器在比较null时抛出NullPointerException
。nullsFirst()
方法(和nullsLast()
类似)基本上将Comparator
转换为新的Comparator
。您放入了一个比较器,如果它试图比较null,它可能会引发异常,并且它吐出一个新的比较器,该比较器的工作方式相同,但它允许使用null参数。所以这就是为什么需要nullsFirst
的参数的原因-因为它会在现有比较器之上构建一个新的比较器,并告诉您现有的比较器是什么。那么,如果您省略该参数,为什么不给您自然顺序呢?因为他们没有那样定义。 javadoc中的
nullsFirst
定义为采用参数:static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator)
我认为,如果设计人员愿意,他们可以添加一个不带参数的重载:
static <T> Comparator<T> nullsFirst() // note: not legal
这与使用
nullsFirst(naturalOrder())
相同。但是他们没有,所以您不能那样使用它。