我想使用Java 8以递归方式列出计算机上的所有文件。
Java 8提供了一个listFiles
方法,它返回所有文件和目录但没有递归。如何使用它来获取完整的递归文件列表(不使用变异集合)?
我已经尝试了下面的代码,但它只有一个深度:
static Function<Path, Stream<Path>> listFiles = p -> {
if (p.toFile().isDirectory()) {
try { return Files.list(p); }
catch (Exception e) { return Stream.empty(); }
} else {
return Stream.of(p);
}
};
public static void main(String[] args) throws IOException {
Path root = Paths.get("C:/temp/");
Files.list(root).flatMap(listFiles).forEach(System.out::println);
}
使用return Files.list(p).flatMap(listFiles);
无法编译(不确定原因)......
注意:我对涉及FileVisitors或外部库的解决方案不感兴趣。
答案 0 :(得分:20)
通过递归遍历文件系统来生成路径流的新API是Files.walk
。
如果你真的想要递归地生成一个流(不一定要走文件树,但我会继续使用它作为一个例子),使用方法引用完成递归可能会更直接:
class RecursiveStream {
static Stream<Path> listFiles(Path path) {
if (Files.isDirectory(path)) {
try { return Files.list(path).flatMap(RecursiveStream::listFiles); }
catch (Exception e) { return Stream.empty(); }
} else {
return Stream.of(path);
}
}
public static void main(String[] args) {
listFiles(Paths.get(".")).forEach(System.out::println);
}
}
方法引用对于将具有相同“形状”(参数和返回类型)的命名方法作为该功能接口的功能接口进行调整非常有用。这也避免了在实例或静态变量中存储lambda并以递归方式调用自身的潜在初始化循环。
答案 1 :(得分:4)
显然不可能通过方法引用引用该函数定义中的函数,但它适用于lambda。
因此,在函数中,return Files.list(p).flatMap(listFiles);
不会编译,return Files.list(p).flatMap(q -> listFiles.apply(q));
会编译。
以递归方式打印给定文件夹中的所有文件:
static final Function<Path, Stream<Path>> listFiles = p -> {
if (p.toFile().isDirectory()) {
try { return Files.list(p).flatMap(q -> listFiles.apply(q)); }
catch (Exception e) { return Stream.empty(); }
} else {
return Stream.of(p);
}
};
public static void main(String[] args) throws IOException {
Path root = Paths.get("C:/temp/");
Files.list(root).flatMap(listFiles).forEach(System.out::println);
}
但正如所指出的那样,这是不必要的:
Files.walk(root).forEach(System.out::println);
做同样的事情......