将 Comparator 与 nullsLast 一起使用时出现 NullPointerException

问题描述 投票:0回答:2

我知道对于同一个问题有很多类似的问题。但是,我已经尝试过提供的解决方案,但没有一个对我有用。我 100% 确定这是我缺少的一些基本内容,但我无法找到问题所在,因此在这里询问...

我有一个像这样的自定义对象:

public class ClassA {
    private int id;
    private Integer min1;
    private Integer min2;
}

在另一个类(

ClassB
)中,我有一个需要排序的
ClassA
对象列表。第一个项目应该是那些在任何
min
属性中具有较低值的项目。如果两个对象具有相同的值,那么哪个先执行并不重要。例如,如果我有这些对象:

身份证 分钟1 分钟1
1 10
2 30
3 80
4 23
5 10

订单应为(ID):1, 5, 4, 2, 3。

为了实现这一目标,我有一个返回

Comparator
:

的方法
public static Comparator<ClassA> compareMins(Function<ClassA, Integer> min) {
    return Comparator.comparing(minuto, Comparator.nullsLast(Comparator.naturalOrder()));
}

ClassB
中,我获取比较器并对列表进行排序,如下所示:

Comparator<ClassA> comparator = ClassA.compareMins(ClassA::getMin1)
    .thenComparing(ClassA::getMin2);
lista.sort(comparator);

但是,在比较对象 ID

NullPointerException
1
时,它会抛出
5
。我猜想,由于
min1
具有相同的值,它会尝试比较 min2,它为空,因此抛出此异常。但是,我无法找到解决方案。任何帮助将非常感激。

java list sorting nullpointerexception comparator
2个回答
0
投票

看起来您忘记再次使用空值比较器

compareMins

Comparator<ClassA> comparator = compareMins(ClassA::min1).thenComparing(compareMins(ClassA::min2));

正如您现在所拥有的,使用

.thenComparing(ClassA::getMin2)
这将评估
min2
的两个实例,并调用
a.min2.compareTo(b.min2)
而不是您在
compareMins
中创建的空值友好检查。


0
投票

编程不是魔法,也不像人类。 “按我的意思做”并不是这样的。

Comparator<ClassA> comparator = ClassA.compareMins(ClassA::getMin1)
   .thenComparing(ClassA::getMin2);
lista.sort(comparator);

这忠实地执行了您所写的内容,但这不是您的意思。

nullsLast
逻辑由
compareMins
的作用来应用。然后,您链接
thenComparing(ClassA::getMin2)
,很明显,最后不会执行任何 null 操作。怎么可能呢?编译器无法嗅出‘嘿,compareMins
似乎做了一些 nullsLast 魔法,我是否认为程序员
意图将相同的 nullsLast 逻辑应用于getMin2
?呃,我会在黑暗中进行一次疯狂的尝试:可能是的,所以我就这么做。

显然,编译器是如何工作的。

默认情况下,所有比较器 NPE 都针对 null,因为 null 没有任何明显的排序,并且最好它们之间甚至没有排序(null 既不高于也不低于也不等于任何其他

null

 - 
null
 是最好的处理方式为“未知”。给定 2 个未知值,不可能说出哪一个更高或更低,也不可能判定它们相等)。

您可以按照目前为止使用的风格进行修复,但您选择的风格听起来不正确。

一个更明显的方法是创建一个方法或函数来完成“返回这两个值中较小的一个,忽略空值”的工作。标准库没有这个功能;它是一种编程语言,您可以在其中编写您想要的内容。它不是一盒乐高积木,工作内容只是找到合适的积木并将它们拼接在一起。有时你必须自己做,可以这么说。

class classA { .... public int getLowest() { return min1 == null ? min2 : min2 == null ? min1 : Math.min(min1, min2); } } listA.sort(Comparator.comparingInt(ClassA::getLowest));
仅当对于 ClassA 的任何实例,

min1

min2
 均为 
null
 时,此操作才会失败。崩溃可能是正确的(这似乎是任意的/试图解决未知问题的错误),但如果你不希望这样,你可以选择:

class classA { .... public Integer getLowest() { return min1 == null ? min2 : min2 == null ? min1 : Math.min(min1, min2); } } listA.sort( Comparator.comparing( ClassA::getLowest, Comparator.nullsLast(Comparator.naturalOrder()) ) );
    
© www.soinside.com 2019 - 2024. All rights reserved.