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

Sag*_*gar 16 java file-io java-8 try-with-resources java-stream

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

List<String> rows = Files.lines(inputFilePath).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 19

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

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

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

有趣的是以下属性Stream.flatMap(…):

每个映射的流在其内容放入此流后关闭.

所以上面的代码将关闭行流.虽然它看起来更简洁,但它比使用资源尝试更有缺点,当前实现flatMap 缺乏惰性评估,这与此无关,因为您无论如何都要将所有行收集到列表中.但是在其他场景中使用这个技巧时要记住这一点.


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

List<String> rows = Files.readAllLines(inputFilePath);
Run Code Online (Sandbox Code Playgroud)

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

  • @neXus `.flatMap(Stream::of)` 为每个元素创建一个新的单元素流,并将它们展平回与 flatMap 之前相同的流。这些单元素流将被关闭,但这没有任何效果。 (3认同)

Sot*_*lis 12

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

返回的流封装了一个Reader.如果需要及时处理文件系统资源,try-with-resources则应使用该构造来确保在流操作完成后调用流的close方法.

所以是的,在声明中包装Stream返回的.(或者适当地关闭它.)linestry-with-resources