Java 8 Stream(基于资源).iterator()自动关闭资源? [英] Java 8 Stream (based on resource) .iterator() that auto-closes the resource?

查看:170
本文介绍了Java 8 Stream(基于资源).iterator()自动关闭资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Does Java 8 Stream.iterator() auto-close the stream when it's done? I suppose not...

我有这样的事情:

class Provider implements Serializable {

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

这个迭代器被其他一些类使用知道迭代器是基于文件读取资源的。那是

This iterator is used by some other class that doesn't know the iterator is based on a file-reading resource. That is

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

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

I have to stream the file because it's too large to fit into memory. But I'd like to be able to auto-close the resource when the iterator doesn't have any more elements, so that I don't have leaked resources. The Provider class is Serializable and I can't have either the Stream or the BufferedReader as members.

有没有好办法呢?

推荐答案

首先,请注意从 BufferedReader.lines 创建的流不包含任何资源,因此关闭流无效:

First, please note that your stream created from BufferedReader.lines does not hold any resource, thus closing the stream has no effect:

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

通常,如果流拥有资源,则会明确记录。例如, Files.lines 记录了这个:

Usually it's explicitly documented if the stream holds a resource. For example, Files.lines documents this:


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

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.

BufferedReader.lines 文档。

因此,在您的情况下,如果它实际上拥有需要关闭的资源,则您有责任关闭 BufferedReader 。情况并非总是如此。例如,如果你创建 new BufferedReader(new StringReader(string)),你就没有任何资源要关闭,所以不要调用 close()方法。

So in your case it's your responsibility to close the BufferedReader if it actually holds a resource which needs to be closed. That's not always the case. For example, if you create new BufferedReader(new StringReader(string)), you don't have any resource to close, so it's just as fine not to call the close() method at all.

无论如何,回到你的问题。假设流实际上拥有一个资源(例如从 Files.lines()创建),如果你只是返回一个迭代器,它将不会自动关闭,无论迭代器是否是走到最后还是没走。如果要在某个特定时刻关闭它,则必须在流上显式调用 close()方法。否则你必须依赖垃圾收集器,它最终将底层资源Object(例如 FileInputStream )放入最终化队列,最终将调用 finalize 该对象的关闭文件的方法。你无法保证何时发生这种情况。

Anyways, back to your question. Assuming that the stream actually holds a resource (e.g. created from Files.lines()), it will not be closed automatically if you just return an iterator, regardless whether the iterator is traversed to the end or not. You have to explicitly call the close() method on the stream if you want to close it at some particular moment. Otherwise you have to rely on garbage collector which will eventually put the underlying resource Object (e.g. FileInputStream) into the finalization queue which will eventually call the finalize method of that object which will close the file. You cannot guarantee when this happens.

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

An alternative would be to buffer the whole input file into memory (assuming that it's not very long) and close the file before returning an iterator. You can do this for reading the file without any stream API:

return Files.readAllLines(pathToTheFile).iterator();

这篇关于Java 8 Stream(基于资源).iterator()自动关闭资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆