致命异常:java.lang.IllegalArgumentException:比较方法违反了它的一般契约
Fatal Exception: java.lang.IllegalArgumentException: Comparison method violates its general contract
我知道有很多类似的问题,通过阅读这些问题的答案我得到了很大的帮助,但是我看不出我的客户是如何面对这个问题的。而且只有一个客户遇到这个问题。
我有一个列表,我正在使用 Comparator 界面对该列表进行排序。你们中有人看到以下代码有问题吗?
private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
@Override
public int compare(BiologySample left, BiologySample right) {
if (left == right || (left != null && right != null && left.getSampleDateTime() == right.getSampleDateTime())) {
return 0;
}
if (left == null || left.getSampleDateTime() == null) {
return 1;
}
if (right == null || right.getSampleDateTime() == null) {
return -1;
}
return right.getSampleDateTime().compareTo(left.getSampleDateTime());
}
}
这就是我调用此函数的方式
Collections.sort(biologySamples, new BiologySamplesComparator());
我知道这种场景的主要问题是传递性。但是我不知道是什么违反了那个规则。
getSampleDateTime() 返回日期 4 月 9 日星期五 17:00:00 PDT 2021
更新
这就是我解决问题的方法。
我希望这会有所帮助,我在这个问题上被困了很长时间。
private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
@Override
public int compare(BiologySample left, BiologySample right) {
if (left == null) {
if (right == null) {
return 0;
} else {
return 1;
}
} else if (right == null) {
return -1;
} else if (left == right) {
return 0;
}
if (left.getSampleDateTime() == null) {
if (right.getSampleDateTime() == null) {
return 0;
} else {
return 1;
}
} else if (right.getSampleDateTime() == null) {
return -1;
} else if (left.getSampleDateTime() == right.getSampleDateTime()) {
return 0;
}
return right.getSampleDateTime().compareTo(left.getSampleDateTime());
}
}
将 null
“样本”与具有空时间戳的非空样本进行比较时可能会出现不一致。
Sample a = null;
Sample b = new Sample(null);
bsc.compare(a, b); // -> 1, a > b
bsc.compare(b, a); // -> 1, b > a
首先,如果可能的话,你应该用Instant
替换你的样本class中的Date
,然后让你的生活更简单地说:
public static final Comparator<Sample> ORDER_BY_TIMESTAMP =
Comparator.nullsLast(Comparator.comparing(
Sample::getDateTime,
Comparator.nullsLast(Comparator.naturalOrder())
);
如果可以排除空值,就更简单了:
Comparator.comparing(Sample::getDateTime);
我在某些情况下遗漏了一些条件,这就是我解决问题的方法。
private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
@Override
public int compare(BiologySample left, BiologySample right) {
if (left == null) {
if (right == null) {
return 0;
} else {
return 1;
}
} else if (right == null) {
return -1;
} else if (left == right) {
return 0;
}
if (left.getSampleDateTime() == null) {
if (right.getSampleDateTime() == null) {
return 0;
} else {
return 1;
}
} else if (right.getSampleDateTime() == null) {
return -1;
} else if (left.getSampleDateTime() == right.getSampleDateTime()) {
return 0;
}
return right.getSampleDateTime().compareTo(left.getSampleDateTime());
}
}
由
提供
我知道有很多类似的问题,通过阅读这些问题的答案我得到了很大的帮助,但是我看不出我的客户是如何面对这个问题的。而且只有一个客户遇到这个问题。
我有一个列表,我正在使用 Comparator 界面对该列表进行排序。你们中有人看到以下代码有问题吗?
private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
@Override
public int compare(BiologySample left, BiologySample right) {
if (left == right || (left != null && right != null && left.getSampleDateTime() == right.getSampleDateTime())) {
return 0;
}
if (left == null || left.getSampleDateTime() == null) {
return 1;
}
if (right == null || right.getSampleDateTime() == null) {
return -1;
}
return right.getSampleDateTime().compareTo(left.getSampleDateTime());
}
}
这就是我调用此函数的方式
Collections.sort(biologySamples, new BiologySamplesComparator());
我知道这种场景的主要问题是传递性。但是我不知道是什么违反了那个规则。
getSampleDateTime() 返回日期 4 月 9 日星期五 17:00:00 PDT 2021
更新 这就是我解决问题的方法。 我希望这会有所帮助,我在这个问题上被困了很长时间。
private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
@Override
public int compare(BiologySample left, BiologySample right) {
if (left == null) {
if (right == null) {
return 0;
} else {
return 1;
}
} else if (right == null) {
return -1;
} else if (left == right) {
return 0;
}
if (left.getSampleDateTime() == null) {
if (right.getSampleDateTime() == null) {
return 0;
} else {
return 1;
}
} else if (right.getSampleDateTime() == null) {
return -1;
} else if (left.getSampleDateTime() == right.getSampleDateTime()) {
return 0;
}
return right.getSampleDateTime().compareTo(left.getSampleDateTime());
}
}
将 null
“样本”与具有空时间戳的非空样本进行比较时可能会出现不一致。
Sample a = null;
Sample b = new Sample(null);
bsc.compare(a, b); // -> 1, a > b
bsc.compare(b, a); // -> 1, b > a
首先,如果可能的话,你应该用Instant
替换你的样本class中的Date
,然后让你的生活更简单地说:
public static final Comparator<Sample> ORDER_BY_TIMESTAMP =
Comparator.nullsLast(Comparator.comparing(
Sample::getDateTime,
Comparator.nullsLast(Comparator.naturalOrder())
);
如果可以排除空值,就更简单了:
Comparator.comparing(Sample::getDateTime);
我在某些情况下遗漏了一些条件,这就是我解决问题的方法。
private static class BiologySamplesComparator implements Comparator<BiologySample>, Serializable {
@Override
public int compare(BiologySample left, BiologySample right) {
if (left == null) {
if (right == null) {
return 0;
} else {
return 1;
}
} else if (right == null) {
return -1;
} else if (left == right) {
return 0;
}
if (left.getSampleDateTime() == null) {
if (right.getSampleDateTime() == null) {
return 0;
} else {
return 1;
}
} else if (right.getSampleDateTime() == null) {
return -1;
} else if (left.getSampleDateTime() == right.getSampleDateTime()) {
return 0;
}
return right.getSampleDateTime().compareTo(left.getSampleDateTime());
}
}
由