简体   繁体   English

Java Stream生命周期回调

[英]Java Stream lifecycle callbacks

Does there exist an elegant way to register callbacks when the last element of the stream has been processed and the stream is "consumed" fully? 当流的最后一个元素被处理并且流被完全“消耗”时,是否存在一种优雅的方式来注册回调?

Especially when the stream source (like a DB cursor, an Iterator<T> , or a custom Supplier<T> ) is finite and can explicitly know when there is no more data. 特别是当流源(如DB游标, Iterator<T>或自定义Supplier<T> )是有限的并且可以明确知道何时没有更多数据。

Example: 例:

public Stream<Row> query(String sql){
   Connection c = dataSource.openConnection();
   Stream<Row> rows = MyDB.query(sql).stream();
   c.close();
   return rows;
}

Now, it's futile to immediately close the connection, rather it would be great to schedule connection closure when the stream is fully consumed. 现在,立即关闭连接是徒劳的,相反,当流完全耗尽时安排连接关闭会很好。

I know there is onClose() API but this relies on consumers explicitly call close() on the stream. 我知道有onClose() API,但这依赖于消费者在流上显式调用close()

You want to register a stream close handler : 您想要注册一个流关闭处理程序

public Stream<Row> query(String sql){
    Connection c = dataSource.openConnection();
    return MyDB.query(sql).stream().onClose(() -> c.close());
}

A caller of this method must excplicitely close the stream! 这种方法的调用者必须以惊人的方式关闭流!

(Note: I left out exception handling here.) (注意:我在这里省略了异常处理。)

Call onClose , and document that the returned stream must be closed by caller. 调用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);
        }
    });
}

A utility that works mostly, except when the returned stream is not iterated to the end: 一个主要工作的实用程序,除非返回的流没有迭代到最后:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM