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万条流。但是,由于让一个流保持打开状态仍然不是一种干净的行为,因此我在编辑时提供了完整的代码。