public static Comparator<Container> DEPARTURE = new Comparator<Container>() {
@Override
public int compare(Container container1, Container container2) {
if (container1.departure.time.isBefore(container2.departure.time))
return -1;
else if (container1.departure.time.equals(container2.departure.time) &&
container1.departure.maxDuration == container2.departure.maxDuration &&
container1.departure.transportCompany.equals(container2.departure.transportCompany) &&
container1.departure.transportType == container2.departure.transportType)
return 0;
else
return +1;
}
};
偏离变量只是包含以下字段的对象的一个实例:
public DateTime time;
public int maxDuration;
public TransportType transportType;
public String transportCompany;
附言时间对象是来自 Joda-Time 库的 DateTime 实例,TransportType 是包含常量火车、海船、驳船和卡车的枚举。
编辑:
好的,所以我将比较器编辑为以下内容:
public static Comparator<Container> DEPARTURE = new Comparator<Container>() {
@Override
public int compare(Container container1, Container container2) {
if (container1.departure.time.isBefore(container2.departure.time))
return -1;
else if (container1.departure.time.isBefore(container2.departure.time))
return +1;
else {
if (container1.departure.maxDuration == container2.departure.maxDuration && container1.departure.transportType == container2.departure.transportType && container1.departure.transportCompany.equals(container2.departure.transportCompany))
return 0;
else
return +1;
}
}
};
但这显然违反了一般契约。我如何让它按时间排序,然后根据它们的其他属性对那些具有相等时间的对象进行排序,只关心它们是否相等?希望这有意义…
编辑:解决方案
谢谢大家回答我的问题!在研究了你的评论后,我想出了下面的解决方案,它似乎是有效的(尽管还没有经过彻底的测试):
我实际上将比较部分移到了离开他的班级,因为我也需要按到达进行比较。我决定简单地按所有属性(连续时间、最大持续时间、传输公司和运输类型)进行排序,我想出的解决方案是:
public static Comparator<Container> ARRIVAL = new Comparator<Container>() {
@Override
public int compare(Container container1, Container container2) {
return container1.arrival.compareTo(container2.arrival);
}
};
public static Comparator<Container> DEPARTURE = new Comparator<Container>() {
@Override
public int compare(Container container1, Container container2) {
return container1.departure.compareTo(container2.departure);
}
};
然后使用compareTo方法:
@Override
public int compareTo(LocationMovement lm) {
if (this.time.isBefore(lm.time))
return -1;
else if (this.time.isAfter(lm.time))
return +1;
else {
int c = this.maxDuration - lm.maxDuration;
if (c != 0) return c;
c = this.transportCompany.compareTo(lm.transportCompany);
if (c != 0) return c;
c = this.transportType.ordinal() - lm.transportType.ordinal();
return c;
}
}
请注意,如果两个容器< code>c1和< code>c2具有相同的< code > department . time ,但其他属性不同,则< code>compare(c1,c2)和< code>compare(c2,c1)都将返回< code> 1,即< code>c1
相反,您应该完全删除其他字段,或者在出发时间相等的情况下在嵌套或顺序 if-else
s 中单独比较它们。
看看这个相关问题的答案,了解一种通过多个属性比较对象的干净方法。
为了实现compare
,您检查的所有项目都必须具有相互“较小”、“较大”或“相等”的概念,然后您必须决定检查它们的顺序,对第一个不相等的项目返回较小/较大。这样,您就满足了合同,即compare(a,b)
必须是compare(b,a)
的反面。如果您正在比较的所有部分都没有“较大”或“较小”的概念(例如,传输类型),那么要么您无法实现compare
,要么您必须强制对它们进行任意(但可靠)的较大/较小解释。
这是一个概念性的例子。在这种情况下,我选择的顺序(任意)是:时间、持续时间、公司和类型。但是不同的顺序可能更合理。这只是一个例子。此外,您还没有说明< code>transportType的类型是什么,所以我假设它有一个< code>compareTo方法;显然,它可能不会,你可能需要调整。
public static Comparator<Container> DEPARTURE = new Comparator<Container>() {
@Override
public int compare(Container container1, Container container2) {
int rv;
// Times
rv = container1.departure.time.compareTo(container2.departure.time);
if (rv == 0) {
// Duration
if (container1.departure.maxDuration < container2.departure.maxDuration) {
rv = -1;
}
else if (container1.departure.maxDuration > container2.departure.maxDuration) {
rv = 1;
}
else {
// Transport company
rv = container1.departure.transportCompany.compareTo(container2.departure.transportCompany);
if (rv == 0) {
// Transport type
rv = container1.departure.transportType.compareTo(container2.departure.transportType);
}
}
}
return rv;
}
};
一般合同是
COMPARATOR.compare(a, b) = - COMPARATOR.compare(b, a)
在您的例子中,一方面返回-1的代码可能另一方面返回0。
有人能解释一下为什么我下面的比较器有时候会抛出上面的异常吗? 注意:myObject 中的 id 字段类型为 long。 解决方案: 基于@amit的回答
我有时会得到一个 for 我可以始终如一地抛出此异常,实时数据运行足够长的时间,但我不确定如何解决问题的实际原因。 我的比较仪有什么问题?(具体来说,我违反了合同的哪一部分?)如何在不掩盖异常的情况下修复它? 我使用的是 Java 7,如果不进行重大重写就无法升级。 我可以通过将设置为来掩盖异常,但这不是一个理想的解决方案。 我尝试创建测试来随机生成数据并验证每个合同条件。我无法抛出异常。 我尝试
我制作了一个带有jPanel和JLabel数组的调色板。起初它运行良好,但后来我从 JPanel 中取出了一些其他 jLabels,并添加了一些事件。现在我不断收到此错误: 我试图删除第一次收到此错误后所做的一切,但仍然不断收到它。当我将布局从 GridLayout 更改为其他任何内容时,错误消失了,但代码变得无用。所以我需要网格布局。当我将该 JPanel 中的所有内容移动到另一个 JPanel
问题内容: 有人可以简单地向我解释一下,为什么此代码会引发异常,“比较方法违反了它的一般约定!”,我该如何解决? 问题答案: 你的比较器不是可传递的。 让是的父,并成为母公司。既然和,那一定是这样。但是,如果在和上调用比较器,它将返回零,即。这违反了合同,因此引发异常。 该库可以很好地检测到这一点并让你知道,而不是行为不规律。 满足传递性要求的一种方法是遍历整个链,而不仅仅是查看直接祖先。
我在整理名单 排序代码: FinalSentence类标头: compareTo()实现: 这是例外: 对于一个小列表(少于 50 个元素),它可以工作。对于一个大型列表(它也应该与那些一起使用),它会引发此异常。列表的实例类型是 ArrayList,这并不重要。 我不知道如何深入了解这一点。列表已满,元素类型相同(那里没有多态性),但是对于大型列表,我得到了这个奇怪的例外。 有什么想法吗? 谢谢
我有这个代码。getCreatedAt 是一个长整型,表示记录的时间戳。 当我使用足够的数据(列表中大约有 200 个项目)运行它时。我开始遇到这个异常 java.lang.IllegalArgumentException:比较方法违反了它的一般约定! 当然,当我编写此代码时,我意识到理论上它可以具有整数溢出,但感觉不太可能,因为时间戳将相隔几天或几周,而不是几十年。 我现在已经通过总是返回1、-