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

是否有正确的方法来关闭在java流api中打开的资源(对于每个元素)?,java,resources,java-stream,autocloseable,Java,Resources,Java Stream,Autocloseable,是否有正确的方法为集合中的每个元素打开资源,而不是使用流api,使用资源执行一些map()、filter()、peek()等操作,然后关闭资源 我有这样的想法: List name=getAllNames(); names.stream().map(n->getElementFromName(n)) .filter(e->e.someCondition()) .peek(e->e.doSomething()) .filter(e->e.otherCondition()) .peek(e->e.

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

我有这样的想法:

List name=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.dothelasthing());
这应该可以正常工作,除非我在getElementFromName方法中打开一个资源(例如db连接)。然后我在其他实例方法中使用该资源,比如someCondition或doSomething。我不知道如何正确关闭它

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

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

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


我还知道,使用foreach-lopp可以很容易地完成,我只是想知道是否可以使用stream-api来完成。

您可以创建第二个列表来存储遇到的元素。不幸的是,这是我所知道的使用流关闭所有元素的唯一方法。

在本例中,我假设
getElementFromName
返回类型为
Element
的对象:

List elements=new ArrayList();//或者任何你想要的清单
列表名称=getAllNames();
names.stream().map(n->getElementFromName(n))
.peek(e->elements.add(e))//将元素添加到列表中
.filter(e->e.someCondition())
.peek(e->e.doSomething())
.filter(e->e.otherCondition())
.peek(e->e.doSomethingElse())
.filter(e->e.lastCondition())
.forEach(e->e.dothelasthing());
elements.forEach(e->e.close());//关闭所有元素

您可以使用
flatMap
进行以下操作:

.flatMap(n -> {
    YourResource r = getElementFromName(n);
    return Stream.of(r).onClose(r::close);
})
这假定由返回元素封装的资源具有
close()
方法。如果不是,代码会变得更复杂,但图片应该清晰。不只是返回单个对象,而是返回单个元素流,其操作将执行必要的清理。如果它可以抛出选中的异常,那么您还必须为此添加一个处理程序,最好将异常包装在未选中的异常中

这取决于为以下各项提供的担保:

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


但通常,此代码,尤其是过度使用的代码,看起来非常可疑。

一旦您从getElementFromName中的数据库中提取了数据,您还需要数据库连接吗?还是仅仅是你已有的数据?非常感谢你的回答。我只是在玩流api,因为我想用它来学习它。为了说明问题,我故意把它写得有点过头了。
.flatMap(n -> {
    YourResource r = getElementFromName(n);
    return Stream.of(r).onClose(r::close);
})