首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java8比较器nullsFirst naturalOrder混淆

Java8比较器nullsFirst naturalOrder混淆
EN

Stack Overflow用户
提问于 2014-10-14 00:39:27
回答 3查看 41.1K关注 0票数 20

这可能是一个简单的问题,但我想清楚地理解它.

我有这样的密码:

代码语言:javascript
复制
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+'}';}    
 }

我正在测试这个代码:

代码语言:javascript
复制
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);                           
}

这表明了以下结果:

代码语言:javascript
复制
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)对象并传递比较器时:

代码语言:javascript
复制
final Comparator<Persona>comparator = comparing(Persona::getName);

就像一种魅力。我是按natural order of name property分类的。当我用name=null添加对象时,问题就出现了,我只是认为我需要像这样的比较器。

代码语言:javascript
复制
final Comparator<Persona>comparator = comparing(Persona::getName,nullsFirst());

我的想法是错误的:“好的,当名称为非空的时候,它们就像以前的比较器一样在natural order of name中排序,如果它们是null,它们将是第一个,但是我的非空名称仍然按自然顺序排序”。

但正确的代码是:

代码语言:javascript
复制
final Comparator<Persona>comparator = comparing(Persona::getName,nullsFirst(naturalOrder()));

我不明白nullsFirst的参数。我只是认为natural order of name将显式地默认,甚至处理null值。

但医生说:

返回一个空友好比较器,该比较器认为null小于非空。当两者都是null时,它们被认为是平等的。如果两者都为非空,则使用指定的Comparator来确定顺序.如果指定的比较器是null,则返回的比较器认为所有非空值都相等。

这一行:“如果两者都是非空的,则使用指定的Comparator来确定顺序。”

我搞不懂什么时候以及如何明确地设置自然秩序,或者什么时候推断自然秩序。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-10-14 01:40:42

当您使用只有一个参数的comparing时,“自然顺序”比较器不会处理空值。(我不知道你是从哪里想到的。)Comparable类的“自然顺序”由compareTo()方法定义,其用法如下:

代码语言:javascript
复制
obj1.compareTo(obj2)

显然,如果obj1为null,这是行不通的;对于String,如果obj2为null,则也会引发异常。

naturalOrder()方法返回一个比较两个对象的Comparatorjavadoc显式地指出,此比较器在比较null时抛出NullPointerException

nullsFirst()方法(以及类似的nullsLast() )基本上将Comparator转换为新的Comparator。您输入了一个比较器,如果它尝试比较null,它可能抛出一个异常,并且它会产生一个新的比较器,它的工作方式与它允许空参数的方式相同。这就是为什么nullsFirst需要一个参数--因为它在现有比较器的基础上构建了一个新的比较器,然后告诉它现有的比较器是什么。

那么,如果省略了参数,它为什么不给出自然的顺序呢?因为他们不是这样定义的。nullsFirstjavadoc中定义为接受参数:

代码语言:javascript
复制
static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator)

我认为如果设计师愿意的话,他们可以增加一个不需要参数的过载:

代码语言:javascript
复制
static <T> Comparator<T> nullsFirst()  // note: not legal

这与使用nullsFirst(naturalOrder())是一样的。但他们没有,所以你不能那样用它。

票数 35
EN

Stack Overflow用户

发布于 2015-06-02 12:30:42

尝试:

代码语言:javascript
复制
final Comparator<Persona> comparator =
  comparing(Persona::getName, nullsFirst(naturalOrder()));
票数 25
EN

Stack Overflow用户

发布于 2017-02-13 16:44:44

我有一份有学生姓名和身份证的员工名单..。

代码语言:javascript
复制
 import java.util.ArrayList;
import java.util.Iterator;

import java.util.List;
import java.util.Comparator;

public class TestClass {

    public static void main(String[] args) {

        Student s1 = new Student("1","Nikhil");
        Student s2 = new Student("1","*");
        Student s3 = new Student("1",null);
        Student s11 = new Student("2","Nikhil");
        Student s12 = new Student("2","*");
        Student s13 = new Student("2",null);
        List<Student> list = new ArrayList<Student>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s11);
        list.add(s12);
        list.add(s13);

        list.sort(Comparator.comparing(Student::getName,Comparator.nullsLast(Comparator.naturalOrder())));

        for (Iterator iterator = list.iterator(); iterator.hasNext();) {
            Student student = (Student) iterator.next();
            System.out.println(student);
        }


    }

}

产生输出

代码语言:javascript
复制
Student [name=*, id=1]
Student [name=*, id=2]
Student [name=Nikhil, id=1]
Student [name=Nikhil, id=2]
Student [name=null, id=1]
Student [name=null, id=2]
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26350996

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档