Stream 上的 collect 操作是否会关闭流和底层资源?

Does collect operation on Stream close the stream and underlying resources?

是否需要将以下代码包装在 try-with-resources 中以确保底层文件已关闭?

List<String> rows = Files.lines(inputFilePath).collect(Collectors.toList());

正如重载 Files#lines(Path, Charset) 方法的 javadoc 所述

The returned stream encapsulates a Reader. If timely disposal of file system resources is required, the try-with-resources construct should be used to ensure that the stream's close method is invoked after the stream operations are completed.

所以是的,将 lines 返回的 Stream 包装在 try-with-resources 语句中。 (或者 close 适当。)

有一个技巧可以使Stream实现在终端操作后调用close()

List<String> rows = Stream.of(Files.lines(inputFilePath)).flatMap(s->s)
                   .collect(Collectors.toList());

它只是创建一个流,将行流封装为单个项目,并使用 flatMap 和身份函数(Function.identity() 也可以)再次将其转换为行流.

有趣的一点是 property of Stream.flatMap(…):

Each mapped stream is closed after its contents have been placed into this stream.

所以上面的代码将关闭行流。虽然它看起来更简洁,但它的缺点是 try with resources that current implementation of flatMap which is not relevant here as you is collecting all lines into a list anyway.但是在其他场景中使用这个技巧时要记住这一点。


对于问题的代码,有一个更简单的解决方案:

List<String> rows = Files.readAllLines(inputFilePath);

读取所有行并关闭所有资源…