在对文件进行排序时,比较方法违反了其一般约定 [英] Comparison method violates its general contract when sorting files

查看:56
本文介绍了在对文件进行排序时,比较方法违反了其一般约定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有很多关于这种异常的问题,我确实找到了解决方案,但是我的问题是,不同项目中的相同代码不会在这种情况下引发异常。这两个项目都具有相同版本的Java和其他库。

I know there are a lot of questions with this kind of exception, and I did found the solution, but my problem is that the same code in different project doesn't throw an exception while this one does. Both projects have the same version of Java and other libraries.

基本上,我有这个小功能,可以从目录中检索文件列表,按时间戳排序,然后返回列表绝对文件名:

Basically I have this small function that retrieves list of files from directory, sorts them by timestamp, and then returns list of absolute file names:

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:比较方法违反了其一般合同!

Basically, in one of the projects this code executes as expected, while in other project it throws IllegalArgumentException: Comparison method violates its general contract!

我知道<$ c自1.7起,$ c> TimSort 是Java中的默认排序方式,该解决方案之一是使用强制使用旧版 MergeSort 的属性。我没有走那条路...相反,我以 此处

I know that TimSort is default sort in Java since 1.7, and that one of the solutions is to use a property which forces usage of legacy MergeSort. I didn't go that route... Instead I "cached" files and their timestamps as sugested 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),然后处理每个文件:

Now, there are multithreading concerns so let me explain what my code does: I have a task scheduler which, with fixed delay, calls method getFiles(String), and then handles each file:

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

            }

        }
    };
}

当应用启动时,此代码称为:

And when the app boots this code is called:

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

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

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

Basically this is the way both of my projects handle files. My question is: why does the first getFiles(String) method work in one project and not the other? If they used different versions of Java or other libraries (like Apache commons-io) I'd understand, but they use same versions.

编辑#1: FileLastModifierPair.java:

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


推荐答案

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

It's likely that in one case the file modification time of some files changes during the sorting, so the sorting position changes. One day this might occur in another project as well. An approach to make a snapshot of the directory by caching these times looks correct to me.

这篇关于在对文件进行排序时,比较方法违反了其一般约定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆