Recursive stream

前端 未结 2 938
孤城傲影
孤城傲影 2020-12-08 10:57

I want to list all the files on my computer recursively using Java 8.

Java 8 provides a listFiles method that returns all the files and directories but

相关标签:
2条回答
  • 2020-12-08 11:29

    It is apparently not possible to refer to a function within that function definition through a method reference but it works with a lambda.

    So in the function, return Files.list(p).flatMap(listFiles); does not compile but return Files.list(p).flatMap(q -> listFiles.apply(q)); does.

    This prints all the files in the given folder recursively:

    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);
    }
    

    but as pointed out, this is unnecessary:

    Files.walk(root).forEach(System.out::println);
    

    does the same thing...

    0 讨论(0)
  • 2020-12-08 11:33

    A new API to generate a stream of Paths by walking the filesystem recursively is Files.walk.

    If you really want to generate a stream recursively (not necessarily walking the file tree, but I'll continue using that as an example), it might be a bit more straightforward to accomplish the recursion using method references:

    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);
        }
    }
    

    Method references turn out to be quite useful for adapting a named method that has the same "shape" (arguments and return type) as a functional interface to that functional interface. This also avoids the potential initialization circularity with storing a lambda in an instance or static variable and calling itself recursively.

    0 讨论(0)
提交回复
热议问题