Java 8 Stream(基于资源).iterator() 自动关闭资源?

2024-01-11

Java 8 吗Stream.iterator()完成后自动关闭流? 我想不是...

我有这样的事情:

class Provider implements Serializable {

  Iterator<String> iterator() {
    Stream<String> stream = new BufferedReader(...).lines();
    return stream.iterator();
  }
}

该迭代器由其他不知道迭代器基于文件读取资源的类使用。那是

class Consumer {
  void f() {
    Iterator<String> iterator = provider.iterator();
    // code that calls iterator methods at non-determined times
  }
}

我必须流式传输该文件,因为它太大而无法装入内存。但我希望能够在迭代器没有更多元素时自动关闭资源,这样我就不会泄漏资源。这Provider类是Serializable我不能将 Stream 或 BufferedReader 作为成员。

有没有好的方法可以做到这一点?


首先,请注意您的流创建自BufferedReader.lines不持有任何资源,因此关闭流没有效果:

BufferedReader br = new BufferedReader(...);
try(Stream<String> stream = br.lines()) {
   ... use stream
}
// br is still open here!

通常,如果流持有资源,则会明确记录。例如,Files.lines https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#lines-java.nio.file.Path-java.nio.charset.Charset-记录了这一点:

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

里面没有这样的备注BufferedReader.lines https://docs.oracle.com/javase/8/docs/api/java/io/BufferedReader.html#lines--文档。

因此,就您而言,您有责任关闭BufferedReader如果它确实拥有需要关闭的资源。情况并非总是如此。例如,如果您创建new BufferedReader(new StringReader(string)),您没有任何要关闭的资源,所以不调用也很好close()根本没有方法。

无论如何,回到你的问题。假设流实际上拥有一个资源(例如从Files.lines()),如果只是返回一个迭代器,无论迭代器是否遍历到末尾,都不会自动关闭。您必须明确调用close()如果您想在某个特定时刻关闭流,请使用流上的方法。否则,您必须依赖垃圾收集器,它最终会将底层资源对象(例如FileInputStream)进入终结队列,最终将调用finalize该对象的方法将关闭文件。您无法保证这种情况何时发生。

另一种方法是将整个输入文件缓冲到内存中(假设它不是很长)并在返回迭代器之前关闭文件。您可以在没有任何流 API 的情况下读取文件:

return Files.readAllLines(pathToTheFile).iterator();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 8 Stream(基于资源).iterator() 自动关闭资源? 的相关文章

随机推荐