Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我的比较器方法如何违反其总合同? 第三方软件包 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 - Fatal编程技术网

我的比较器方法如何违反其总合同? 第三方软件包 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);

让我们从头开始。我对代码的理解是,比较器的逻辑是正确的。(我本来可以避免使用null
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