递归流

我想使用Java 8以递归方式列出计算机上的所有文件。

Java 8提供了一个listFiles方法,该方法返回所有文件和目录,但没有递归。 如何使用它来获取完整的递归文件列表(不使用变异集合)?

我已经尝试了下面的代码,但它只有一个深度:

 static Function<Path, Stream> 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或外部库的解决方案不感兴趣。

通过递归遍历文件系统来生成Paths流的新API是Files.walk

如果你真的想要递归地生成一个流(不一定要走文件树,但我会继续使用它作为一个例子),使用方法引用完成递归可能会更直接:

 class RecursiveStream { static Stream 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); } } 

方法引用对于将具有相同“形状”(参数和返回类型)的命名方法作为该function接口的function接口进行调整非常有用。 这也避免了在实例或静态变量中存储lambda并递归调用自身的潜在初始化循环。

显然不可能通过方法引用引用该函数定义中的函数,但它适用于lambda。

所以在函数中, return Files.list(p).flatMap(listFiles); 不编译但return Files.list(p).flatMap(q -> listFiles.apply(q)); 确实。

这将以递归方式打印给定文件夹中的所有文件:

 static final Function> 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); 

做同样的事情……