当前位置: 首页 > 知识库问答 >
问题:

比较方法在对文件进行排序时违反了其一般约定

孔乐邦
2023-03-14

我知道这种异常有很多问题,我也找到了解决方案,但我的问题是不同项目中的相同代码不会抛出异常,而这个会。两个项目都有相同版本的Java和其他库。

基本上,我有一个小函数,它从目录中检索文件列表,按时间戳对它们进行排序,然后返回绝对文件名列表:

public static List<String> getFiles(String dir) {

    List<String> fileList = new ArrayList<String>();
    File[] files = new File(dir).listFiles();

    // Sort files by the date of their creation (last modification)
    Arrays.sort(files, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR);

    for (File f : files) {
        fileList.add(f.getAbsolutePath());
    }
    return fileList;

}

基本上,在其中一个项目中,这段代码按预期执行,而在另一个项目中,它抛出< code > IllegalArgumentException:Comparison方法违反了它的一般契约!

我知道从1.7开始,TimSort是Java中的默认排序,解决方案之一是使用强制使用传统MergeSort的属性。我没有走那条路…相反,我“缓存”文件及其时间戳,如下所示:

public static List<String> getFiles(String dir) {

    List<String> fileList = new ArrayList<String>();
    File[] files = new File(dir).listFiles();

    FileLastModifiedPair[] pairs = new FileLastModifiedPair[files.length];
    for (int i = 0; i < files.length; i++) {
        pairs[i] = new FileLastModifiedPair(files[i]);
    }

    // Sort files by the date of their creation (last modification)
    Arrays.sort(pairs);

    // Take the sorted pairs and extract only the file part, discarding the timestamp
    for (FileLastModifiedPair pair : pairs) {
        fileList.add(pair.f.getAbsolutePath());
    }
    return fileList;
}

现在,有多线程问题,所以让我解释一下我的代码的作用:我有一个任务调度器,它以固定的延迟调用方法getFiles(String),然后处理每个文件:

private Thread handleFiles () {
    return new Thread() {
        public void run() {

            List<String> files = getFiles("/home/user/files/");
            if (files.isEmpty()) {
                return;
            }

            for (String file : files) {
                try {
                    // handle file...
                } catch (Exception e) {
                    // log error...
                } finally {
                    // delete file...
                }

            }

        }
    };
}

当应用程序启动时,将调用此代码:

    Date startOfTomorrow = DateTime.now()
            .withTimeAtStartOfDay()
            .plusDays(1)
            .toDate();

    scheduler.scheduleWithFixedDelay(
            handleFiles(),
            startOfTomorrow,
            DELAY_IN_MILLIS);

基本上,这是我的两个项目处理文件的方式。我的问题是:为什么第一个getFiles(String)方法在一个项目中工作而不是另一个项目?如果他们使用不同版本的Java或其他库(如Apache commons-io),我会理解,但他们使用相同的版本。

编辑#1:FileLastModifierPair.java:

public class FileLastModifiedPair implements Comparable<FileLastModifiedPair> {
    public File f;
    public long t;

    public FileLastModifiedPair(File file) {
        f = file;
        t = file.lastModified();
    }

    public int compareTo(FileLastModifiedPair that) {
        long result = this.t - that.t;

        if (result < 0) {
            return -1;
        } else if (result > 0) {
            return 1;
        } else {
            return 0;
        }
    }
}

共有2个答案

钱繁
2023-03-14

我猜在一个项目中,一些文件在排序时被修改了。这肯定会扰乱排序算法,并解释你得到的错误。另请参见Java错误:比较方法违反了它的一般合同

钦德佑
2023-03-14

很可能在一种情况下,某些文件的文件修改时间在排序过程中发生了变化,因此排序位置也发生了变化。有一天,这也可能发生在另一个项目中。在我看来,通过缓存这些时间来创建目录快照的方法是正确的。

 类似资料:
  • 从昨天开始,我的代码中出现了错误,我不知道为什么!我用谷歌搜索了很多,找到了这个堆栈帖子。 我使用这个功能按名称对用户进行排序并创建日期。这个功能已经工作了2年,现在我收到一个用户的错误,我不知道发生了什么变化。我试图检查我的数据是否有任何损坏,但找不到任何问题。 读完zhe Stack-Post后,我仍然没有完全理解问题出在哪里,或者我的项目发生了什么变化。

  • 我想通过dateLastContact比较两个“收件人”,如果相同,就通过地址进行比较。这是我的代码: 而且我总是有这个错误: 我尝试了很多方法,但是现在,我不知道该怎么办。你能帮我吗? 收件人类别:

  • 以下几行: 返回以下异常:比较方法违反了其一般约定! 我知道这个异常通常是在没有正确实现比较方法时产生的,但是在我的例子中,它的实现是相当明显的: 正如您所看到的,目标是按照值的hashValue属性对值进行排序。 任何关于我做错了什么的想法/提示将不胜感激! 谢谢托马斯

  • 我收到以下错误: 比较方法违反了其总合同! 这是我的比较法 我想比较项目的分数。但是当分数相同时,我想按名称对它们进行排序。 我需要更改什么,为什么会出现这个错误? 编辑: 分数是一个,itemname一个。 这是 ComparableItem 类: 这是MenuList项目类:

  • 是的,我知道有很多问题与相同的问题,但我似乎真的找不到我的比较器有什么问题。 所以,这里是: 代码非常简单:我需要根据它们如何改变我的主要结构对一些对象进行排序,并且我首先想要最高值。 由于计算或对象的影响可能需要一些时间,我只是缓存值以便重用它们,因此在排序之前,我检查是否有缓存值或是否需要计算它。 一旦我计算出将< code>m1或< code>m2应用于我的结构的结果,我就将更改恢复。 你可

  • 我知道有很多问题与这个主题有关,但我不能完全理解是什么导致了这个错误 有人知道为什么它不起作用以及如何修复它吗?