Using the Java 8 Stream API, I would like to register a \"completion hook\", along the lines of:
Stream stream = Stream.of(\"a\",
The solution I've come up with looks like this:
class AutoClosingStream implements Stream {
AutoClosingStream(Stream delegate, Consumer> onComplete) {}
// Pipeline ops delegate the op to the real stream and wrap that again
@Override
public Stream limit(long maxSize) {
return new AutoClosingStream(delegate.limit(maxSize), onComplete);
}
// Terminal ops intercept the result and call the onComplete logic
@Override
public void forEach(Consumer super T> action) {
terminalOp(() -> delegate.forEach(action));
}
private void terminalOp(Runnable runnable) {
terminalOp(() -> { runnable.run(); return null; });
}
private R terminalOp(Supplier supplier) {
R result = null;
try {
result = supplier.get();
onComplete.accept(Optional.empty());
}
catch (Throwable e) {
onComplete.accept(Optional.of(e));
Utils.sneakyThrow(e);
}
return result;
}
}
This is only a simplified sketch to illustrate the idea. The real solution would also support the primitive IntStream, LongStream, and DoubleStream