【问题标题】:Does collect operation on Stream close the stream and underlying resources?Stream 上的 collect 操作是否会关闭流和底层资源?
【发布时间】:2015-09-19 05:03:22
【问题描述】:

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

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

【问题讨论】:

标签: java file-io java-8 java-stream try-with-resources


【解决方案1】:

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

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

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

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

每个映射的流在其内容放入该流后关闭。

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


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

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

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

【讨论】:

  • 我尝试了您的解决方案,它有效。我还假设它等同于Files.lines(inputFilePath).flatMap(Stream::of),但令我惊讶的是它不是。后者实际上并没有关闭流。 (在 jdk1.8.0_221 上)
  • @neXus .flatMap(Stream::of) 为每个元素创建一个新的单个元素流,并将它们展平为与 flatMap 之前相同的流。那些单元素流将被关闭,但这没有任何效果。
【解决方案2】:

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

返回的流封装了一个Reader。如果及时处置档案 系统资源是必需的,try-with-resources 构造应该 用于确保流的 close 方法在 流操作已完成。

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

【讨论】:

    猜你喜欢
    • 2010-11-14
    • 2015-08-31
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    相关资源
    最近更新 更多