Java Stream生命周期回调

时间:2019-06-13 08:56:21

标签: java java-stream

在处理完流的最后一个元素并且流已“完全消耗”时,是否存在一种优雅的方法来注册回调?

特别是当流源(例如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()

3 个答案:

答案 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);
}