Bertolla
Bertolla

Reputation: 3

Sorting an array of files by date in name

I need to sort an array of files by the date which is part of the name of the file e.g.: "20200611_2130.dat". I tried doing it with:

Arrays.sort(files,new FileNameComparator());
public class FileNameComparator implements Comparator<File> {
    private static SimpleDateFormat formatter =
            new SimpleDateFormat("YYYYddMM_HHmm");

    @Override
    public int compare(File a, File b) {
        try {
            return asTime(a.getName()) > asTime(b.getName()) ? 1 : -1;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    private static long asTime(String filename) throws ParseException {
        return formatter.parse(
                filename.substring(0, filename.lastIndexOf("."))).getTime();

    }
}

I know there is a lot to fix here, but right now I would like to understand why I get:

"Comparison method violates its general contract!"

Upvotes: 0

Views: 122

Answers (3)

user14940971
user14940971

Reputation:

Code review:

  • Change your pattern to "yyyyddMM_HHmm" if 20200611_2130.dat is Fri Nov 06 21:30:00.
  • You should return something in the catch block, for example Long.MIN_VALUE.
  • Add a second comparator if the filename is not a date, for example compare as strings.

Your code might look something like this:

private static SimpleDateFormat formatter =
        new SimpleDateFormat("yyyyddMM_HHmm");

private static long asTime(String filename) {
    try {
        Date date = formatter.parse(
                filename.substring(0, filename.lastIndexOf(".")));
        return date.getTime();
    } catch (ParseException e) {
        return Long.MIN_VALUE;
    }
}
public static void main(String[] args) {
    String[] fileNames = {
            "20200611_2130.dat",
            "20201511_2130.dat",
            "20200605_2130.dat",
            "20100611_2130.dat",
            "picture.jpg"};

    Arrays.sort(fileNames, Comparator
            .<String>comparingLong(name -> asTime(name))
            .thenComparing(Comparator.naturalOrder()));

    Arrays.stream(fileNames).forEach(System.out::println);
}

Output:

picture.jpg
20100611_2130.dat
20200605_2130.dat
20200611_2130.dat
20201511_2130.dat

Upvotes: 0

Kush Singh
Kush Singh

Reputation: 317

@Bertolla you need to add a equals case. if equal return 0 else -1. then do a greater or smaller comparison case.

Upvotes: 0

codiallo
codiallo

Reputation: 183

Your comparator not works when a==b. It has to return 0. Your current implementation returns -1. You should consider the case where a==b and return 0 if true, then handle the case where filenames are different.

Upvotes: 1

Related Questions