Якщо файли, які Ви сортуєте, можна одночасно змінювати або оновлювати, то сортування виконується:
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;
}
Обидва ці рішення створюють тимчасову структуру даних карт, щоб заощадити постійний останній змінений час для кожного файлу в каталозі. Причиною, що нам потрібно зробити це, є те, що якщо ваші файли оновлюються або змінюються під час виконання сортування, то ваш компаратор буде порушувати вимогу про транзитивність загального контракту інтерфейсу компаратора, оскільки останні порівнянні часи можуть змінюватися під час порівняння.
Якщо, з іншого боку, ви знаєте, що файли не будуть оновлюватися чи змінюватися під час вашого сортування, ви можете отримати майже будь-яку іншу відповідь, подану на це запитання, з якої я частково:
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)
.sorted(Comparator.comparing(File::lastModified))
.map(File::toPath) // remove this line if you would rather work with a List<File> instead of List<Path>
.collect(Collectors.toList());
}
}
Примітка. Я знаю, що ви можете уникнути перекладу до та з Файлових об’єктів у наведеному вище прикладі, використовуючи файл Files :: getLastModifiedTime api в режимі відсортованого потоку, однак тоді вам потрібно мати справу з перевіреними винятками IO всередині вашої лямбда, що завжди є болем . Я б сказав, якщо продуктивність достатньо критична, що переклад неприйнятний, то я б або мав справу з перевіреною IOException в лямбда, розповсюджуючи її як UncontIOException, або я б відмовився від файлів api і працював лише з об'єктами File:
final List<File> sorted = Arrays.asList(new File(directoryPathString).listFiles());
sorted.sort(Comparator.comparing(File::lastModified));