如果文件夹中有大量文件或使用非 SSD 存储,则对 File.listFiles() 和 File.isDirectory(或 isFile)的调用会使文件夹扫描变得非常缓慢。可以一步进行扫描,但按目录/文件排序仍将再次重复对 isDirectory/isFile 的调用。
相反,您应该考虑使用Files.find 实现,这意味着您可以同时读取所有文件属性,这样排序就不会再次重新读取文件系统属性。它在一个流中被巧妙地处理。这是一个仅打印当前文件夹的排序项目和修改时间的示例:
public static Stream<Map.Entry<Path, BasicFileAttributes>>
find(Path dir, int maxDepth, BiPredicate<Path, BasicFileAttributes> matcher, FileVisitOption... options) throws IOException {
// Using ConcurrentHashMap is safe to use with parallel()
ConcurrentHashMap<Path,BasicFileAttributes> attrs = new ConcurrentHashMap<>();
BiPredicate<Path, BasicFileAttributes> predicate = (p,a) -> (matcher == null || matcher.test(p, a)) && attrs.put(p, a) == null;
return Files.find(dir, maxDepth, predicate, options).map(p -> Map.entry(p, attrs.remove(p)));
}
public static void main_sort_files(String[] args) throws IOException {
Path dir = Path.of(args[0]);
int depth = 1;
// Note it is easy to add more sort fields here:
Comparator<Entry<Path, BasicFileAttributes>> compDirs = Comparator.comparing(entry -> entry.getValue().isRegularFile());
Comparator<Entry<Path, BasicFileAttributes>> comparing = compDirs.thenComparing(entry -> entry.getKey().getFileName().toString(), String.CASE_INSENSITIVE_ORDER);
try(var files = find(dir, depth, (p,a) -> true)) {
files.sorted(comparing).forEach(entry -> System.out.println(entry.getKey() +" modified "+entry.getValue().lastModifiedTime()));
// Alternatively get files+folder Paths:
// List<Path> contents = files.sorted(comparing).map(Entry::getKey).toList();
}
}
可以通过将深度编辑为 Integer.MAX_VALUE 来进行树扫描。
编辑
由于您更喜欢处理地图,您可以更改 find 方法以直接返回地图并分别对键进行排序,或者您可以将排序后的条目放入 LinkedHashMap 以使用标准 for 循环进行迭代,例如:
try(var files = find(dir, depth, (p,a) -> true)) {
Map<Path, BasicFileAttributes> sorted = files.sorted(comparing)
.collect(Collectors.toMap(Entry::getKey, Entry::getValue,
(a,b) -> a, LinkedHashMap::new));
for (var entry : sorted.entrySet()) {
BasicFileAttributes attr = entry.getValue();
Path path = entry.getKey();
System.out.println((attr.isDirectory() ? "DIR ":"FILE ")+path +" modified "+attr.lastModifiedTime());
}
}