Java流生命周期回调
当流的最后一个元素被处理并且流被完全“消耗”时,是否存在一种优雅的方法来注册回调 尤其是当流源(如DB游标、Java流生命周期回调,java,java-stream,Java,Java Stream,当流的最后一个元素被处理并且流被完全“消耗”时,是否存在一种优雅的方法来注册回调 尤其是当流源(如DB游标、迭代器或自定义供应商)是有限的,并且可以明确知道何时没有更多数据时 例如: public Stream<Row> query(String sql){ Connection c = dataSource.openConnection(); Stream<Row> rows = MyDB.query(sql).stream(); c.close();
迭代器或自定义供应商
)是有限的,并且可以明确知道何时没有更多数据时
例如:
public Stream<Row> query(String sql){
Connection c = dataSource.openConnection();
Stream<Row> rows = MyDB.query(sql).stream();
c.close();
return rows;
}
公共流查询(字符串sql){
连接c=dataSource.openConnection();
Stream rows=MyDB.query(sql.Stream();
c、 close();
返回行;
}
现在,立即关闭连接是徒劳的,相反,在流被完全消耗时安排关闭连接会更好
我知道有onClose()
API,但这依赖于用户在流上显式调用close()
。您想注册一个:
公共流查询(字符串sql){
连接c=dataSource.openConnection();
返回MyDB.query(sql.stream().onClose(()->c.close());
}
此方法的调用方必须异常地关闭流
(注意:我在这里遗漏了异常处理。)调用,并记录调用者必须关闭返回的流
/**
* The returned stream must be closed.
*/
public Stream<Row> query(String sql){
Connection c = dataSource.openConnection();
return MyDB.query(sql).stream().onClose(() -> {
try {
c.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
}
/**
*必须关闭返回的流。
*/
公共流查询(字符串sql){
连接c=dataSource.openConnection();
返回MyDB.query(sql).stream().onClose(()->{
试一试{
c、 close();
}捕获(SQLE异常){
抛出新的运行时异常(e);
}
});
}
一种主要工作的实用程序,除非返回的流没有迭代到底:
public <T> Stream<T> wrap(Stream<T> stream, Runnable onEnd) {
final Object endSignal = new Object();
return Stream.concat(stream, Stream.of(endSignal))
.peek(i -> {
if(i == endSignal){onEnd.run();}
})
.filter(i -> i != endSignal)
.map(i -> (T) i);
}
public Stream wrap(Stream-Stream,Runnable-oned){
最终对象endSignal=新对象();
返回流concat(流,流of(endSignal))
.peek(i->{
如果(i==endSignal){onEnd.run();}
})
.filter(i->i!=结束信号)
.map(i->(T)i);
}
这是否意味着流的使用者必须显式地调用流上的close()
?例如,假设流是以迭代器作为源构建的。所以,当源迭代器的hasNext()
返回false
?@s.D.是的,调用方必须调用close,或者使用try with resources,就像调用方在任何其他资源绑定流上所需做的一样,比如返回的那些流。没有自动的“流用完”回调,因为流可能永远不会用完。@ernest_k,因为终端操作可能不会完全使用流。假设您有一个名为s
的流,以及以下代码:s.limit(10).forEach(…)
。这只消耗前10个值,因此您可以执行其他操作来处理其余的值。只有你自己才能确定何时处理完流,因此关闭流是你的责任。@Andreas你知道允许“处理其余部分”的实际流源吗?@Slaw我想,语言是那么弱,因为stream
是一个接口。当您尝试多次使用引用实现时,它将引发异常。另一种可能是可以返回新流的源,但是,不能保证流只从源中获取这些元素,它在概念上会消耗,特别是并行流会进行预取。例如,BufferedReader
明确表示,一旦处理了它的lines()
流,它就处于未定义状态。所以这里没有“处理其余的”。我不知道有什么反例。
public <T> Stream<T> wrap(Stream<T> stream, Runnable onEnd) {
final Object endSignal = new Object();
return Stream.concat(stream, Stream.of(endSignal))
.peek(i -> {
if(i == endSignal){onEnd.run();}
})
.filter(i -> i != endSignal)
.map(i -> (T) i);
}