是否有正确的方法来关闭在 java 流 api 中打开的资源(对于每个元素)?

use*_*960 5 java resources java-stream autocloseable

是否有正确的方法为集合中的每个元素打开资源,而不是使用流 api,使用资源执行一些 map()、filter()、peek() 等而不是关闭资源?

我有这样的事情:

List<String> names =  getAllNames();
names.stream().map(n -> getElementFromName(n))
              .filter(e -> e.someCondition())
              .peek(e -> e.doSomething())
              .filter(e -> e.otherCondition())
              .peek(e -> e.doSomethingElse())
              .filter(e -> e.lastCondition())
              .forEach(e -> e.doTheLastThing());
Run Code Online (Sandbox Code Playgroud)

这应该可以正常工作,除了我在 getElementFromName 方法中打开一个资源(例如数据库连接)。然后我在其他实例方法(如 someCondition 或 doSomething)中使用该资源。我不知道如何正确关闭它。

我知道,我只在流上使用中间操作。这意味着,所有方法都在 forEach 操作中进行评估,性能应该没问题,因为迭代只完成一次。

但是我不知道如何关闭为 getElementFromName 方法中的每个元素打开的资源。

我可以保存由 getElementFromName 创建的所有元素的列表并稍后关闭资源。但我只会浪费空间,让所有资源保持活力。此外,还会对元素列表进行第二次迭代。在这种情况下,这使得避免流 api 更可取。那么有没有办法在我使用完元素后以某种方式自动关闭资源?

我也知道,它可以使用 foreach lopp 轻松完成,我只是好奇是否可以使用流 api 完成。

Hol*_*ger 2

您可以flatMap为此使用:

\n\n
.flatMap(n -> {\n    YourResource r = getElementFromName(n);\n    return Stream.of(r).onClose(r::close);\n})\n
Run Code Online (Sandbox Code Playgroud)\n\n

这假设返回元素封装的资源具有该close()方法。如果没有,代码会变得更复杂,但图片应该很清晰。您\xe2\x80\x99 不只是返回单个对象,而是返回一个单元素流,其onClose操作执行必要的清理。如果它可以抛出已检查的异常,则您\xe2\x80\x99还必须为此添加一个处理程序,最好将异常包装在未检查的异常中。

\n\n

这依赖于以下方面的保证flatMap

\n\n
\n

每个映射的流都是closed在其内容被放入该流之后的。

\n
\n\n

但一般来说,这段代码,尤其是过度使用peek,看起来非常可疑。

\n