首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Files.walk.filter和Files.find有什么区别?

Files.walk.filter和Files.find有什么区别?
EN

Stack Overflow用户
提问于 2017-02-15 15:36:48
回答 2查看 4.7K关注 0票数 8

此代码搜索特定文件:

代码语言:javascript
运行
复制
Stream<Path> findMyFile = Files.find(Paths.get("c:\\temp\\pathtest"), Integer.MAX_VALUE,(p, a) -> p.endsWith("test.txt") && a.isRegularFile());

Stream<Path> findMyFileSecond = Files.walk(Paths.get("c:\\temp\\pathtest"),Integer.MAX_VALUE).filter(p -> p.endsWith("test.txt"));

findMyFile.forEach(System.out::println);
findMyFileSecond.forEach(System.out::println);

这两个结果包含相同的文件,这两个方法几乎在同一时间内完成。JavaDoc说:

与{@代码遍历}方法返回的流*上调用* java.util.stream.Stream#filter过滤器相比,此方法以*# may方法指定的方式遍历文件树,通过*避免冗余检索BasicFileAttributes,这种方法可能更有效

什么时候应该结合使用walkfilter,以及什么时候使用find?什么是最佳做法?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-10 15:53:27

TL;DR:如果您需要按属性过滤掉文件/don-使用Files.find(),如果不需要通过文件属性进行筛选--使用Files.walk()

详细信息

这里有一个细微的差别,这实际上是在文档中解释的,但在某种程度上它感觉完全错误。阅读源代码可以清楚地看到:

  • Files.find: 返回StreamSupport.stream(.).onClose(迭代器::close) .filter(entry -> matcher.test(entry.file(),entry.attributes() .map(entry -> entry.file());
  • Files.walk: 返回StreamSupport.stream(.).onClose(迭代器::close).map(条目-> entry.file());

这意味着,如果在最终的筛选中,您需要获取和验证文件属性-- File.find可能会更快。这是因为使用File.walk,您的过滤器回调将需要一个额外的调用,例如,Files.readAttributes(file, BasicFileAttributes.class),而对于File.find,属性已经被检索并在过滤器回调中提供给您。

我只是在Windows上使用我的示例10K-文件多文件夹结构测试了它,方法是只搜索文件(即不包括文件夹):

代码语言:javascript
运行
复制
// pre-Java7/8 way via recursive listFiles (8037 files returned): 1521.657 msec.
for (File f : new File(dir).listFiles()) {
    if (f.isDirectory()) {
        _getFiles(files, path, pattern);
    } else {
        ...
    }
}

// Files.walk(8037 files returned): 1575.766823 msec.
try (Stream<Path> stream = Files.walk(path, Integer.MAX_VALUE) {
    files = stream.filter(p -> {
        if (Files.isDirectory(p)) { return false; } // this extra check makes it much slower than Files.find
        ... 
    }).map(p -> p.toString()).collect(Collectors.toList());
}

// Files.find(8037 files returned): 27.606675 msec.
try (Stream<Path> stream = Files.find(path, Integer.MAX_VALUE, (p, a) -> !a.isDirectory())) {
    files = stream.filter(p -> { ... }).map(p -> p.toString()).collect(Collectors.toList());
}

// Files.walkFileTree(8037 returned): 27.443974 msec.
Files.walkFileTree(new File(path).toPath(), new SimpleFileVisitor<Path>() { 
    @Override
    public FileVisitResult visitFile(Path p, BasicFileAttributes attrs) throws IOException {
        ...
        return FileVisitResult.CONTINUE;
    }
});
票数 9
EN

Stack Overflow用户

发布于 2017-02-15 16:18:31

我相信,如果您需要在应用筛选器或并行化流之前对目录列表应用一些中间操作,那么walk()将是有利的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42253688

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档