Java Comparator.nullsLast与Comparator.comparingInt

Java Comparator.nullsLast与Comparator.comparingInt,java,Java,我有一个比较整数(可以为空)的比较器,所以 我尝试使用比较器。comparingit,但它不起作用: public static final Comparator<Task> sort = Comparator.comparingInt(x -> x.getNumber(), Comparator.nullsLast(null)); 但我想知道为什么,因为我想比较整数,所以compareInt是正确的选择 如何将Compar

我有一个比较整数(可以为空)的比较器,所以

我尝试使用
比较器。comparingit
,但它不起作用:

public static final Comparator<Task> sort = 
Comparator.comparingInt(x -> x.getNumber(), 
                        Comparator.nullsLast(null));
但我想知道为什么,因为我想比较整数,所以compareInt是正确的选择

如何将
Comparator.nullsLast
Comparator.comparingit
结合使用

  • Integer
    int
    不一样。特别是,任何比较int的尝试都无法处理
    null
    ,您在这里确实需要它,所以它是正确的。使用
    比较

  • 您的第一个代码段不起作用,因为您将2个参数传递给
    comparingit
    方法,该方法只接受一个参数:一个lambda,它将给定的
    任务
    转换为
    int
    。这不是使用
    nullsLast
    的方式

  • 您的第二个代码段确实有效,但它的作用完全不同:它首先从
    任务
    中提取一个
    整数
    ,然后使用
    nullsLast
    比较器实现排序。这意味着空值将是最后一个,是的,,并且所有其他整数将以任意顺序排列。正如我所说,这不是使用
    nullsLast
    的方式

  • 这就是如何使用
    nullsLast

    案例:您的任务列表包含null而不是任务:
    someListOfTasks.sort(Comparator.nullsLast(Comparator.comparating(task::getNumber))

    案例:任务列表中包含一个数字为null的任务:
    someListOfTasks.sort(Comparator.comparing(任务::getNumber,Comparator.nullsLast(Comparator.naturalOrder()))

    (我想这就是你想要的)

    案例:您的任务列表既包含null而不是tasks,也包含一些数字为null的任务:
    someListOfTasks.sort(Comparator.nullsLast(Comparator.comparating(task::getNumber,Comparator.nullsLast(Comparator.naturalOrder())))

    这可能会让人觉得有些罗嗦,但请注意,一个null与另一个null没有关系,您可能希望null任务条目首先排序,而带有null数字的非null任务最后排序。您的问题中没有任何内容表明您的列表中有空任务,因此您需要第二个示例

    那么这意味着什么呢?
    Comparator.comparing(valueExtractor,valueComparator)
    是通用语法。您可以省略
    valueComparator
    部分,在这种情况下,您将获得所谓的“自然排序”。对于整数,它是
    0,1,2,3,4….
    ——显而易见的一个。对于随机对象,如果它们实现了
    Comparable
    (java.lang.Integer
    实现了这一点),那么将实现您尝试排序的对象的
    compareTo
    方法

    请注意,根据定义,自然顺序不能处理null(毕竟,尝试在null上调用
    compareTo
    与在任何null ref上调用任何实例方法所做的相同:它抛出
    NullPointerException
    )。您可以通过不使用自然顺序,而是使用nullsFirst或nullsLast比较器来“修复”该问题。这些“包装”是一个比较器,因此语法为:

    Comparator.nullsLast(comparatorToWrap)

    这意味着:首先,将所有空值排序到底。然后,要比较所有非空条目,请使用
    comparatorToWrap
    。在您发布的代码片段中,您已在此处为
    comparatorToWrap
    传入了
    null
    nullsLast
    的规范明确指出:这意味着所有非空值都被认为是相等的,这意味着,如果排序列表、任意顺序,对于映射/集,只有一个非空键:任意一种方式,而不是您想要的。显然,您希望具有非空数字的任务按照整数的自然顺序进行排序,即具有数字“1”的任务的排序应高于具有数字“2”的任务的排序。因此,传入自然顺序比较器:
    comparator.nullslat(comparator.naturalOrder())
    ——这意味着:首先将所有null排序到底,然后根据此处的自然顺序对其余的进行排序

    然后,您希望将此概念(“最后排序为null,其余按自然顺序排序”)应用于任务本身,而不是应用于
    task.getNumber()
    返回的任何内容,因此,我们首先需要一个lambda来提取(因此,
    task::getNumber
    x->x.getNumber()
    ,它们的含义相同),然后我们传入
    整数
    比较器以启动:

    Comparator sortIntegersNaturallyWithNullsLast=Comparator.nullsLast(Comparator.naturalOrder());
    函数extractNumber=Task::getNumber;
    排序(Comparator.comparing(extractNumber,sortIntegersNaturallyWithNullsLast));
    
    注意:另一种选择是使任务具有自然顺序:

    公共类任务实现可比较{
    私有整数;
    …这里的其他同学。。
    @覆盖公共整数比较(任务其他){
    整数o=其他数字;
    if(number==null&&o==null)返回0;
    如果(number!=null)返回-1;
    如果(o!=null)返回+1;
    返回编号。与(o)比较;
    }
    }
    

    然后您可以使用
    Comparator.naturalOrder()
    listOfTasks.sort(Comparator.naturalOrder())

    comparingit
    用于返回
    int
    的方法,而不是
    Integer
    。您应该使用
    比较
    。从什么时候开始
    比较
    接受两个参数?有没有办法将
    空值设置
    比较
    结合使用?例如,
    nullsLast(comparingit(x->x.getNumber())
    也不起作用。
    nullsLast(comparing(x->x.getNumber())
    起作用吗?@nimo23好吧,我误解了。你为什么不喜欢你发现有效的解决方案<代码>比较器。比较(x->x.getNumber(),
    The method comparingInt(ToIntFunction<? super T>) 
    in the type Comparator is not applicable for 
    the arguments ((<no type> x) -> {}, Comparator.nullsLast(null))
    
       public static final Comparator<Task> sort = 
       Comparator.comparing(x -> x.getNumber(), 
                           Comparator.nullsLast(null));