我知道对于同一个问题有很多类似的问题。但是,我已经尝试过提供的解决方案,但没有一个对我有用。我 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,它为空,因此抛出此异常。但是,我无法找到解决方案。任何帮助将非常感激。
看起来您忘记再次使用空值比较器
compareMins
:
Comparator<ClassA> comparator = compareMins(ClassA::min1).thenComparing(compareMins(ClassA::min2));
正如您现在所拥有的,使用
.thenComparing(ClassA::getMin2)
这将评估 min2
的两个实例,并调用 a.min2.compareTo(b.min2)
而不是您在 compareMins
中创建的空值友好检查。
编程不是魔法,也不像人类。 “按我的意思做”并不是这样的。
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())
)
);