我的比较器方法如何违反其总合同? 第三方软件包 import java.util.Collections; 导入java.util.Comparator; 导入org.joda.time.DateTime; 我的比较仪 publicstaticcomparatortask\u PRIORITY=newcomparator(){ 公共整数比较(任务task1、任务task2){ if(task1==null&&task2==null)返回0; if(task1==null)返回+1;//最后为null if(task2==null)返回-1;//最后为null //只考虑任务重试5次之后的重试 如果(task1.getRetries()>=5 | | task2.getRetries()>=5){ //主排序:重试计数(升序) int retriesCompare=Integer.compare(task1.getRetries(),task2.getRetries()); 如果(retriesCompare!=0)返回retriesCompare; } //二级排序:创建时间(升序,先空) int creationCompare=compareTimeNullFirst(task1.getCreationTime(),task2.getCreationTime()); 如果(creationCompare!=0)返回creationCompare; //三级排序:加载时间(升序,最后为空) int loadCompare=compareTimeNullLast(task1.getLoadTime(),task2.getLoadTime()); 如果(loadCompare!=0)返回loadCompare; 返回0; } }; 私有静态int compareTimeNullLast(DateTime time1,DateTime time2){ if(time1==null&&time2==null)返回0; if(time1==null)返回+1; if(time2==null)返回-1; if(time1.isBefore(time2)返回-1; 如果(time1.isAfter(time2))返回+1; 返回0; } 私有静态int compareTimeNullFirst(日期时间时间1,日期时间时间2){ if(time1==null&&time2==null)返回0; if(time1==null)返回-1; if(time2==null)返回+1; if(time1.isBefore(time2)返回-1; 如果(time1.isAfter(time2))返回+1; 返回0; } 使用我的比较器 //任务是一个列表 集合。排序(任务、任务优先级); 我的问题
有时,我会收到一个我的比较器方法如何违反其总合同? 第三方软件包 import java.util.Collections; 导入java.util.Comparator; 导入org.joda.time.DateTime; 我的比较仪 publicstaticcomparatortask\u PRIORITY=newcomparator(){ 公共整数比较(任务task1、任务task2){ if(task1==null&&task2==null)返回0; if(task1==null)返回+1;//最后为null if(task2==null)返回-1;//最后为null //只考虑任务重试5次之后的重试 如果(task1.getRetries()>=5 | | task2.getRetries()>=5){ //主排序:重试计数(升序) int retriesCompare=Integer.compare(task1.getRetries(),task2.getRetries()); 如果(retriesCompare!=0)返回retriesCompare; } //二级排序:创建时间(升序,先空) int creationCompare=compareTimeNullFirst(task1.getCreationTime(),task2.getCreationTime()); 如果(creationCompare!=0)返回creationCompare; //三级排序:加载时间(升序,最后为空) int loadCompare=compareTimeNullLast(task1.getLoadTime(),task2.getLoadTime()); 如果(loadCompare!=0)返回loadCompare; 返回0; } }; 私有静态int compareTimeNullLast(DateTime time1,DateTime time2){ if(time1==null&&time2==null)返回0; if(time1==null)返回+1; if(time2==null)返回-1; if(time1.isBefore(time2)返回-1; 如果(time1.isAfter(time2))返回+1; 返回0; } 私有静态int compareTimeNullFirst(日期时间时间1,日期时间时间2){ if(time1==null&&time2==null)返回0; if(time1==null)返回-1; if(time2==null)返回+1; if(time1.isBefore(time2)返回-1; 如果(time1.isAfter(time2))返回+1; 返回0; } 使用我的比较器 //任务是一个列表 集合。排序(任务、任务优先级); 我的问题,java,java-7,comparator,Java,Java 7,Comparator,有时,我会收到一个IllegalArgumentException,因为比较方法违反了它的一般约定!。我可以在实时数据运行足够长的时间后始终引发此异常,但我不确定如何修复问题的实际原因 我的问题 我的比较器出了什么问题?(具体来说,我违反了合同的哪一部分?)我如何在不掩盖例外的情况下修复它 笔记 我使用的是Java7,如果不进行重大重写,就无法升级 我可以通过将java.util.Arrays.useLegacyMergeSort设置为true来掩盖异常,但这不是一个理想的解决方案 我试图创建
IllegalArgumentException
,因为比较方法违反了它的一般约定!
。我可以在实时数据运行足够长的时间后始终引发此异常,但我不确定如何修复问题的实际原因
我的问题
我的比较器出了什么问题?(具体来说,我违反了合同的哪一部分?)我如何在不掩盖例外的情况下修复它
笔记
- 我使用的是Java7,如果不进行重大重写,就无法升级
- 我可以通过将
设置为java.util.Arrays.useLegacyMergeSort
来掩盖异常,但这不是一个理想的解决方案true
- 我试图创建测试来随机生成数据并验证每个异常。我无法获得要抛出的异常
- 我尝试删除重试比较周围的条件,但最终还是得到了异常
- 此行引发异常:
Collections.sort(tasks,TASK_PRIORITY);
Task
和DateTime
值,但这与您的问题无关。)
另一个可能导致此异常的因素是,如果compare
方法给出的结果不一致,因为Task
对象正在更改。实际上,它看起来在语义上对(至少)有意义重试计数要更改。如果有另一个线程正在更改Task
字段,则在当前线程正在排序时会影响排序…这可能会导致illegargumentexception
(比较契约的一部分是,在对集合进行排序时,成对排序不会发生变化。)
然后你说:
我使用ImmutableSet.copyOf
在排序之前复制列表,并在java.util.concurrent.locks.ReadWriteLock
中的读锁下执行此操作
复制集合不会复制集合的元素。它是一个浅层副本。因此,您将得到两个包含相同对象的集合。如果另一个线程变异了任何对象(例如,通过增加重试次数),则可能会更改对象的顺序
锁定可以确保您拥有一致的副本,但这不是问题所在
解决方案是什么?我可以想出几个:
任务
对象字段的快照;例如
public class Key implements Comparable<Key> {
private int retries;
private DateTime creation;
private DateTime load;
private Task task;
public Key(Task task) {
this.task = task;
this.retries = task.getRetryCount();
...
}
public int compareTo(Key other) {
// compare using retries, creation, load
}
}
公共类密钥实现可比较{
私人整数重试;
私有日期时间创建;
私有日期时间负载;
私人任务;
公钥(任务){
this.task=任务;
this.retries=task.getRetryCount();
...
}
公共int比较(关键其他){
//使用重试、创建和加载进行比较
}
}
这样做的潜在优势是,您复制的信息较少,您可以从排序的键
对象集合转到原始的任务
对象请注意,所有这些备选方案都比您当前所做的慢。我认为没有办法避免这种情况。在运行排序时,这些任务是否正在其他线程中更新和重试?换句话说,它们的重试次数是否会在排序过程中发生变化?或者其他数据是否会在排序过程中发生变化?一对任务是否会发生变化在单个分拣操作过程中的不同时间进行不同的比较?@Ryan根据措辞
这不是一个严格的要求,通常是这样,但不是stri