Сортировка Изменение файлов с измененным временем без ошибки сравнения
У меня есть код, который удаляет все файлы в каталоге, за исключением последних n последних измененных. Код получает список объектов File
из каталога, сортирует их с помощью компаратора, который смотрит на File.lastModifedTime()
, а затем удаляет соответствующий подсписчик.
Когда мы перешли на Java 7, программа начала метать java.lang.IllegalArgumentException: Comparison method violates its general contract!
. Я подозреваю, что это связано с тем, что файл изменен (нормальное поведение) до того, как сортировка завершена, поэтому компаратор возвращает несогласованные значения, проверяя каждый последний измененный файл.
Мой вопрос: как бы вы решили эту проблему и удалили нужные файлы?
Одно из предложений, которое я прочитал, состояло в том, чтобы сохранить файл и его последнее модифицированное время на карте перед сортировкой, поэтому при выполнении сравнений последнее измененное время просматривается с карты. Однако, если файл изменил среднюю сортировку, карта не обновляется, так что вы не удалили бы неправильный файл?
Другая идея, о которой я думал, - это использовать файл Java NIO для просмотра отсортированного списка и повторной сортировки всякий раз, когда изменяется файл. Но это кажется довольно сложным.
Я также подумал о методе грубой силы обертывания сортировки в заявлении try-catch и просто повторить весь класс, если он столкнулся с нарушением метода сравнения.
Наконец, я мог бы просто установить свойство java.util.Arrays.useLegacyMergeSort
и вернуться к тихому игнорированию способов Java 6.
Ответы
Ответ 1
Мой вопрос: как бы вы решили эту проблему и удалили нужные файлы?
Я предлагаю вам взять временные метки всех файлов и кешировать их. Сортировка, используя эти тайники. Таким образом, они будут отсортированы с использованием согласованного времени.
File[] files = ...
final Map<File, Long> modified = new HashMap<File, Long>();
for(File file: files)
modified.put(file, file.lastModified());
Arrays.sort(files, /* Comparator using 'modified' Map */);
Ответ 2
Взято из моего ответа на более общий вопрос. Лучший способ перечислить файлы в Java, отсортированные по дате изменения?
Ява 8+
private static List<Path> listFilesOldestFirst(final String directoryPath) throws IOException {
try (final Stream<Path> fileStream = Files.list(Paths.get(directoryPath))) {
return fileStream
.map(Path::toFile)
.collect(Collectors.toMap(Function.identity(), File::lastModified))
.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
// .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) // replace the previous line with this line if you would prefer files listed newest first
.map(Map.Entry::getKey)
.map(File::toPath) // remove this line if you would rather work with a List<File> instead of List<Path>
.collect(Collectors.toList());
}
}
Java 7
private static List<File> listFilesOldestFirst(final String directoryPath) throws IOException {
final List<File> files = Arrays.asList(new File(directoryPath).listFiles());
final Map<File, Long> constantLastModifiedTimes = new HashMap<File,Long>();
for (final File f : files) {
constantLastModifiedTimes.put(f, f.lastModified());
}
Collections.sort(files, new Comparator<File>() {
@Override
public int compare(final File f1, final File f2) {
return constantLastModifiedTimes.get(f1).compareTo(constantLastModifiedTimes.get(f2));
}
});
return files;
}