Comparison method violates its general contract when sorting files

对着背影说爱祢 提交于 2019-12-23 20:11:28

问题


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;

}

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

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

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

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.

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

回答1:


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.




回答2:


I guess in one project some of the files are modified while they are sorted. This would certainly mess with the sorting algorithm and would explain the error you get. See also Java error: Comparison method violates its general contract



来源:https://stackoverflow.com/questions/34672595/comparison-method-violates-its-general-contract-when-sorting-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!