Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive stream

Tags:

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 without recursion. How can I use it to get a full recursive list of files (without using a mutating collection)?

I've tried the code below but it only goes one level deep:

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

And using return Files.list(p).flatMap(listFiles); does not compile (not sure why)...

Note: I am not interested in solutions involving FileVisitors or external libraries.

like image 408
assylias Avatar asked Feb 08 '14 13:02

assylias


People also ask

Is stream faster than for loop?

Yes, streams are sometimes slower than loops, but they can also be equally fast; it depends on the circumstances. The point to take home is that sequential streams are no faster than loops.

What is a stream in API?

Streaming APIs are used to read data in real-time from the web for consumers for precise, up-to-date results. For example, they are typically used by social media platforms to deliver media content such as audio and data. Typically Social Networks tend to use WebSocket, which is a subset of Streaming APIS.

What is stream API example?

Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.

What is flatMap in Java stream?

Stream flatMap(Function mapper) returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Stream flatMap(Function mapper) is an intermediate operation. These operations are always lazy.


1 Answers

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.

like image 53
Stuart Marks Avatar answered Oct 13 '22 00:10

Stuart Marks