How to retrieve a list of directories QUICKLY in Java?

后端 未结 14 1011
轮回少年
轮回少年 2020-12-01 12:45

Suppose a very simple program that lists out all the subdirectories of a given directory. Sound simple enough? Except the only way to list all subdirectories in Java is to u

14条回答
  •  不知归路
    2020-12-01 12:58

    I came across similar question when debugging performance in a Java application enumerating plenty of files. It is using old approach

    for (File f : new File("C:\\").listFiles()) {
        if (f.isDirectory()) {
            continue;
        }        
    }
    

    And it appears that each f.isDirectory() is the call into native FileSsystem which, at least on NTFS, is very slow. Java7 NIO has additional API, but not all methods are good there. I'll just provide JMH benchmark result here

    Benchmark                  Mode  Cnt  Score    Error  Units
    MyBenchmark.dir_listFiles  avgt    5  0.437 ?  0.064   s/op
    MyBenchmark.path_find      avgt    5  0.046 ?  0.001   s/op
    MyBenchmark.path_walkTree  avgt    5  1.702 ?  0.047   s/op
    

    Number come from execution of this code:

    java -jar target/benchmarks.jar -bm avgt -f 1 -wi 5 -i 5 -t 1
    
    static final String testDir = "C:/Sdk/Ide/NetBeans/src/dev/src/";
    static final int nCycles = 50;
    
    public static class Counter {
        int countOfFiles;
        int countOfFolders;
    }
    
    @Benchmark
    public List dir_listFiles() {
        List files = new ArrayList<>(1000);
    
        for( int i = 0; i < nCycles; i++ ) {
            File dir = new File(testDir);
    
            files.clear();
            for (File f : dir.listFiles()) {
                if (f.isDirectory()) {
                    continue;
                }
                files.add(f);
            }
        }
        return files;
    }
    
    @Benchmark
    public List path_walkTree() throws Exception {
        final List files = new ArrayList<>(1000);
    
        for( int i = 0; i < nCycles; i++ ) {
            Path dir = Paths.get(testDir);
    
            files.clear();
            Files.walkFileTree(dir, new SimpleFileVisitor () {
                @Override
                public FileVisitResult visitFile(Path path, BasicFileAttributes arg1) throws IOException {
                    files.add(path);
                    return FileVisitResult.CONTINUE;
                }
    
                @Override
                public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes arg1) 
                        throws IOException {
                    return path == dir ? FileVisitResult.CONTINUE : FileVisitResult.SKIP_SUBTREE;
                }
            });
        }
    
        return files;
    }
    
    @Benchmark
    public List path_find() throws Exception {
        final List files = new ArrayList<>(1000);
    
        for( int i = 0; i < nCycles; i++ ) {
            Path dir = Paths.get(testDir);
    
            files.clear();
            files.addAll(Files.find(dir, 1, (path, attrs) 
                    -> true /*!attrs.isDirectory()*/).collect(Collectors.toList()));
        }
    
        return files;
    }
    

提交回复
热议问题