首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Comparator.nullsLast与Comparator.comparingInt

Comparator.nullsLast与Comparator.comparingInt
EN

Stack Overflow用户
提问于 2020-03-02 08:48:39
回答 1查看 1.5K关注 0票数 4

我有一个比较器比较Integer (可以是null),所以

我试着使用Comparator.comparingInt,但它不起作用:

代码语言:javascript
复制
public static final Comparator<Task> sort = 
Comparator.comparingInt(x -> x.getNumber(), 
                        Comparator.nullsLast(null));

我得到编译器错误:

代码语言:javascript
复制
The method comparingInt(ToIntFunction<? super T>) 
in the type Comparator is not applicable for 
the arguments ((<no type> x) -> {}, Comparator.nullsLast(null))

当使用comparing而不是comparingInt时,它起作用:

代码语言:javascript
复制
   public static final Comparator<Task> sort = 
   Comparator.comparing(x -> x.getNumber(), 
                       Comparator.nullsLast(null));

但是我想知道为什么,因为我想比较整数,所以compareInt是正确的选择。

如何将Comparator.nullsLastComparator.comparingInt结合使用?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-02 09:37:35

  1. Integerint不一样。特别是,任何比较int的尝试都无法处理null,这是您在这里确实需要的,所以它很快就会出现。使用comparing.
  2. Your第一段不起作用,因为您要将两个args传递给comparingInt方法,该方法只需要一个:将给定的Task转换为int的lambda。这不是使用nullsLast.
  3. Your第二段的方法,但是它做了完全不同的事情:它首先从Task中提取一个Integer,然后使用nullsLast比较器实现排序。这意味着空值将是最后一个,是的,和所有其他整数都将是任意顺序的。就像我说的,这不是你使用nullsLast.

的方式

这就是您如何使用nullsLast的方法

case:任务列表包含null,而不是任务:

someListOfTasks.sort(Comparator.nullsLast(Comparator.comparing(task::getNumber)));

case:您的任务列表包含一个数字为null的任务:

someListOfTasks.sort(Comparator.comparing(task::getNumber, Comparator.nullsLast(Comparator.naturalOrder())));

(我想这就是你想要的)

大小写:您的任务列表包含两个空值,而不是任务,有些任务的数字为null:

someListOfTasks.sort(Comparator.nullsLast(Comparator.comparing(task::getNumber, Comparator.nullsLast(Comparator.naturalOrder()))));

这可能有点冗长,但请注意,一个null与另一个null没有关系,您很可能希望空任务条目先排序,而非空任务的空号排序。您的问题中没有任何内容表明您的列表中有空任务,因此需要第二个示例。

那这是什么意思?

Comparator.comparing(valueExtractor, valueComparator)是通用语法。您可以省略valueComparator部分,在这种情况下,您将得到所谓的“自然排序”。对于Integer来说,这是0,1,2,3,4.... --显而易见的一个。对于随机对象,如果它们实现了Comparable ( java.lang.Integer这样做),那么您要排序的对象的compareTo方法就实现了。

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

Comparator.nullsLast(comparatorToWrap)

这意味着:首先,将所有空值排序到末尾。然后,要比较所有非空项,请使用comparatorToWrap。在您发布的片段中,您在这里传递了null for comparatorToWrapnullsLast的规范明确规定:这意味着所有非空值都被认为是相等的,这意味着,如果排序列表、任意顺序,对于映射/集,只有一个非空键:,不管是哪种方式,而不是您想要的。您显然希望非空数的任务按照整数的自然顺序排序,即数字'1‘的任务排序应该高于数字'2’的任务。因此,传递自然顺序比较器:Comparator.nullsLast(Comparator.naturalOrder()) -这意味着:首先排序所有的空到最后,然后排序其余的根据什么是自然在这里。

然后,您想要将这个概念(‘排序空最后,其余按自然顺序排列’)不应用于任务本身,而是应用于任何task.getNumber()返回的任务,因此我们首先需要一个提取(so、Task::getNumberx -> x.getNumber();这些都意味着相同的事情)的lambda,然后传入我们的Integer比较器来引导:

代码语言:javascript
复制
Comparator<Integer> sortIntegersNaturallyWithNullsLast = Comparator.nullsLast(Comparator.naturalOrder());

Function<Task, Integer> extractNumber = Task::getNumber;

listOfTasks.sort(Comparator.comparing(extractNumber, sortIntegersNaturallyWithNullsLast));

注:另一种选择是使任务具有自然的顺序:

代码语言:javascript
复制
public class Task implements Comparable<Task> {
    private Integer number;
    .. rest of class here ..

    @Override public int compareTo(Task other) {
        Integer o = other.number;
        if (number == null && o == null) return 0;
        if (number != null) return -1;
        if (o != null) return +1;
        return number.compareTo(o);
    }
}

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

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60485232

复制
相关文章

相似问题

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