java - 比较方法在排序文件时违反了它的一般契约

标签 java file sorting comparator

我知道有很多关于这种异常的问题,我确实找到了解决方案,但我的问题是不同项目中的相同代码不会抛出异常,而这个会抛出异常。这两个项目都具有相同版本的 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 是 Java 自 1.7 以来的默认排序方式,其中一种解决方案是使用强制使用遗留 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 - 比较方法在排序文件时违反了它的一般契约,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34672595/

相关文章:

Java:在其他类中使用迭代器

java - 从 Java 返回 Windows cmd 文本?

file - 如何使用 vba 在具有通用名称的文件中打开某些 excel 文件夹

PHP上传文件名

php - 排序一个整数数组,负整数排在前面,正整数排在后面

java - 如何仅使用 Core Java 将键值对映射注入(inject)到对象中?

java - 为什么我的倒计时器似乎在倒退?

java - 文件删除检测

c++ - 成对 vector : first pair values are non-sorted and second pair values are sorted: how to find a sorted value when having the non-sorted one

sorting - 归并排序——递归树