Jaskaranbir Singh
Jaskaranbir Singh

Reputation: 2034

Why is File::listFiles faster than DirectoryStream - accepting only directories

So I "heard" that DirectoryStream introduced in Java 7 is faster than traditional methods of directory listing. However, this is not the case for me. It might have been faster for listing whole directory, but when filtering out files and only accepting folders, it takes far more time. For instance, these are the codes:

Using File:

ArrayList<File> tempArray = new ArrayList();
for (File file : someFile.listFiles()){
    if(!file.isDirectory())
        continue;
    tempArray.add(file);
}

Using DirectoryStream:

DirectoryStream<Path> stream = null;
try {
    stream = Files.newDirectoryStream(dir, new DirectoryStream.Filter<Path>() {
            public boolean accept(Path file) throws IOException {
                return Files.isDirectory(file);
            }
        });
} catch (IOException ex) {
}

ArrayList<File> files = new ArrayList();
for (Path path : stream)
    files.add(path.toFile());
stream.close();

The second method (using DirectoryStream) is much more slower. I know both methods check each and every file to see if its directory. Or is it because DirectoryStreamis synchronized (again, correct me if wrong)?

Upvotes: 1

Views: 1212

Answers (2)

chengpohi
chengpohi

Reputation: 14217

This is caused by you are using filter predicate in DirectoryStream, Stream with predicate is slower than collection. You can verify it by:

Stream.of(file.listFiles()).filter(f -> f.isDirectory()).collect(Collectors.toList())

Now, you can see, DirectoryStream is faster than listFiles.

So the root cause is not about DirectoryStream and listFiles, it's you are using Stream with filter predicate.

Upvotes: 1

Tassos Bassoukos
Tassos Bassoukos

Reputation: 16142

Well, in the second case you're testing twice that the path is a directory. Further, you're actually defining a new class, which has a relatively large first-use cost.

Upvotes: 1

Related Questions