如果正在排序的文件可以在执行排序的同时被修改或更新:
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());
}
}
Note: I know you can avoid the translation to and from File objects in the above example by using Files::getLastModifiedTime api in the sorted stream operation, however, then you need to deal with checked IO exceptions inside your lambda which is always a pain. I'd say if performance is critical enough that the translation is unacceptable then I'd either deal with the checked IOException in the lambda by propagating it as an UncheckedIOException or I'd forego the Files api altogether and deal only with File objects:
final List<File> sorted = Arrays.asList(new File(directoryPathString).listFiles());
sorted.sort(Comparator.comparing(File::lastModified));