Java 8 终端操作是否关闭该流?
Java 8 终端操作是否关闭该流?,java-8,java-stream,Java 8,Java Stream,dirPath包含200k个文件。我想一个接一个地读,然后做一些处理。以下代码段导致java.nio.file.FileSystemException:dirPath/file-N打开的文件过多。终端操作forEach()是否应该在移动到下一个流之前关闭打开的流(即打开的文件)?换句话说,我是否必须为流文件添加try-with资源 Files.list(dirPath) .forEach(filePath -> { Files.lines(filePa
dirPath
包含200k个文件。我想一个接一个地读,然后做一些处理。以下代码段导致java.nio.file.FileSystemException:dirPath/file-N打开的文件过多
。终端操作forEach()
是否应该在移动到下一个流之前关闭打开的流(即打开的文件)?换句话说,我是否必须为流文件添加try-with资源
Files.list(dirPath)
.forEach(filePath -> {
Files.lines(filePath).forEach() { ... }
});
否
forEach
不关闭流(由Files.list
或Files.lines
创建)。它记录在javadoc中,例如:
返回的流封装了一个读卡器。如果需要及时处理文件系统资源,则应使用try-with-resources构造来确保在流操作完成后调用流的close方法
在大多数情况下,嵌套的
forEach
是错误的工具
代码
Files.list(dirPath).forEach(filePath -> Files.lines(filePath).forEach(line -> { ... });
可以而且应该由
Files.list(dirPath).flatMap(filePath -> Files.lines(filePath)).forEach(line -> { ... });
或者,因为在这种情况下并不那么容易:
Files.list(dirPath).flatMap(filePath -> {
try { return Files.lines(filePath);}
catch(IOException ex) { throw new UncheckedIOException(ex); }
}).forEach(line -> { });
作为副作用,您可以免费获得以下内容:
:
每个映射流在其内容放入该流后关闭
所以这是首选的解决方案。或者,为了使它完全正确:
try(Stream<Path> dirStream = Files.list(dirPath)) {
dirStream.flatMap(filePath -> {
try { return Files.lines(filePath);}
catch(IOException ex) { throw new UncheckedIOException(ex); }
}).forEach(line -> { });
}
try(Stream dirStream=Files.list(dirPath)){
dirStream.flatMap(文件路径->{
请尝试{返回文件.行(文件路径);}
catch(IOException ex){抛出新的未选中的异常(ex);}
}).forEach(第->{}行);
}
我想您可能误读了flatMap的文档。flatMap采用一个本身返回多个流的函数;flatMap所做的是确保从传递给flatMap的函数返回的流在将这些流的结果展平到flatMap返回的流中时关闭。flatMap与map在应用到的流方面没有什么不同。(或者我猜你在随后的编辑中发现了这一点。:)@BarryKelly我从来没有说过,flatMap
对外部流有影响。单个外部流不是OP的问题,而是传递给flatMap
的函数产生的200k流。所以我提供了一个解决方案来关闭这20万条流。但是,由于让一个流保持打开状态仍然不是一种干净的行为,因此我在编辑时提供了完整的代码。