【问题标题】:Comparison method violates its general contract when sorting files排序文件时比较方法违反其一般合同
【发布时间】:2016-01-08 08:33:02
【问题描述】:

我知道这种异常有很多问题,我确实找到了解决方案,但我的问题是不同项目中的相同代码不会抛出异常而这个异常。两个项目都有相同版本的 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;

}

基本上,在其中一个项目中,此代码按预期执行,而在其他项目中则抛出IllegalArgumentException: Comparison method violates its general contract!

我知道TimSort 是自 1.7 以来 Java 中的默认排序,其中一种解决方案是使用强制使用旧版 MergeSort 的属性。我没有走那条路……相反,我按照here的建议“缓存”了文件及其时间戳:

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;
        }
    }
}

【问题讨论】:

标签: java file sorting comparator


【解决方案1】:

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

【讨论】:

  • 我不会更改我的应用程序内外的文件(至少,直到所有文件都被排序然后我开始处理和删除它们)。难道是排序算法改变了 File.lastModified 字段?
【解决方案2】:

我猜在一个项目中,一些文件在排序时被修改了。这肯定会弄乱排序算法并解释你得到的错误。另见Java error: Comparison method violates its general contract

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多