Files.newDirectoryStream()是Java 7引入的高效目录遍历方法,支持延迟加载、内存友好,并原生支持glob字符串或DirectoryStream.Filter接口进行文件过滤。

Files.newDirectoryStream() 是 Java 7 引入的高效、轻量级目录遍历方式,相比 File.listFiles() 或递归 Files.walk(),它延迟加载、内存友好,且原生支持过滤器。要高效遍历特定类型文件(如 .txt、.log),关键在于**正确使用其带 Filter super Path> 参数的重载方法**,而非事后在循环中判断。
用 glob 模式快速匹配后缀(推荐初阶用法)
最简洁的方式是传入一个 glob 字符串,由系统自动编译为高效路径匹配逻辑:
- 语法:使用
"*.ext"匹配当前层级所有.ext文件(不递归,不匹配子目录) - 注意:glob 区分大小写(取决于底层文件系统),Windows 通常不敏感,Linux 敏感
- 示例:只遍历
.java和.xml文件(需两次调用或改用自定义 Filter)
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path, "*.java")) {
for (Path entry : stream) {
System.out.println(entry.getFileName());
}
}
用自定义 Filter 精确控制匹配逻辑(推荐进阶用法)
当需要多后缀、忽略大小写、排除隐藏文件、或结合文件属性(如是否为普通文件)时,应实现 DirectoryStream.Filter<path></path>:
- 必须重写
accept(Path)方法,返回true表示保留该条目 - 务必先用
Files.isRegularFile(p)排除非文件项(如子目录、符号链接),避免误处理 - 用
String.endsWith()+toLowerCase()实现大小写不敏感匹配更可靠
DirectoryStream.Filter<Path> textFilter = p -> {
if (!Files.isRegularFile(p)) return false;
String name = p.getFileName().toString();
return name.toLowerCase().endsWith(".txt") ||
name.toLowerCase().endsWith(".log") ||
name.toLowerCase().endsWith(".csv");
};
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path, textFilter)) {
for (Path entry : stream) {
System.out.println(entry);
}
}
避免常见低效陷阱
- ❌ 不要在循环内调用
Files.isRegularFile()或Files.isDirectory()多次——应在 Filter 中一次性判断并缓存结果 - ❌ 不要用
path.toString().contains(".log")——可能误匹配路径中间部分(如/logs/archive.log.bak) - ❌ 不要对每个文件都调用
Files.probeContentType()——开销大,且不可靠;后缀过滤足够用于大多数场景 - ✅ 若需递归多级匹配,不要嵌套
newDirectoryStream,改用Files.walk()配合filter()流操作(但注意其内存与性能权衡)
补充:组合多个条件的实用写法
可封装常用逻辑为静态工具方法,提升复用性:
- 例如:
Filters.suffixes(".jpg", ".png", ".gif").and(Filters.notHidden()) - 内部仍基于单个
accept()实现,避免对象创建开销 - 比链式 Stream.filter() 更轻量,因
DirectoryStream本身不构建中间集合


















