在处理完流的最后一个元素并且流已“完全消耗”时,是否存在一种优雅的方法来注册回调?
特别是当流源(例如DB游标,Iterator<T>
或自定义Supplier<T>
)是有限的并且可以明确知道何时没有更多数据时。
示例:
public Stream<Row> query(String sql){
Connection c = dataSource.openConnection();
Stream<Row> rows = MyDB.query(sql).stream();
c.close();
return rows;
}
现在,立即关闭连接是徒劳的,而在流被完全用尽时安排关闭连接将是很好的选择。
我知道有onClose()
API,但这依赖于使用者在流上显式调用close()
。
答案 0 :(得分:4)
您要注册stream close handler:
public Stream<Row> query(String sql){
Connection c = dataSource.openConnection();
return MyDB.query(sql).stream().onClose(() -> c.close());
}
此方法的调用者必须明确关闭流!
(注意:我在这里省略了异常处理。)
答案 1 :(得分:4)
调用onClose
,并记录返回的流必须由调用者关闭。
/**
* 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);
}
});
}
答案 2 :(得分:0)
除了返回的流没有循环到最后时,大多数情况下都有效的实用程序:
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);
}