Jee*_*87c 5 java java-8 java-stream
假设我想要重构以下方法
protected Stream<T> parseFile(File file, Consumer<File> cleanup) {
try {
return parser.parse(file); // returns a Stream<T>
} catch (XmlParseException e) { // child of RuntimeException
throw new CustomRuntimeException(e);
} finally {
if (file != null) {
cleanup.accept(file);
}
}
throw new IllegalStateException("Should not happen");
}
Run Code Online (Sandbox Code Playgroud)
此方法的目的是充当代理,在包装异常中的流重新抛出上附加错误处理CustomRuntimeException.因此,当我们稍后在流程中使用它时,我不必在任何地方处理这些异常,而只是处理它们CustomRuntimeException.
上游,我使用的方法如下
try {
Stream<T> stream = parseFile(someFile);
stream.map(t -> ...);
catch (CustomRuntimeException e) {
// do some stuff
}
Run Code Online (Sandbox Code Playgroud)
这就是parser.parse方法的样子
public Stream<T> parse() {
// ValueIterator<T> implements Iterator<T>, AutoCloseable
XmlRootParser.ValueIterator<T> valueIterator = new XmlRootParser.ValueIterator(this.nodeConverter, this.reader, this.nodeLocalName, this.nodeName);
Stream<T> stream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(valueIterator, 1040), false);
stream.onClose(valueIterator::close);
return stream;
}
Run Code Online (Sandbox Code Playgroud)
我想要处理的异常将由ValueIterator.hasNext方法抛出.这意味着它们不会在Stream创建时被抛出,而只会在Stream使用时抛出(在流上调用foreach/map/count/collect/...).
如何在方法中parseFile很好地附加错误处理方法而不必使用流?可能吗?
显然,只有当parser.parse方法在返回之前使用其流时,此代码才有效.哪个是反对使用流.
所述Stream的后端,其提供迭代逻辑,是Spliterator.
所以你可以使用这样的包装器包装元素处理Spliterator:
class Wrapper<T> implements Spliterator<T> {
final Spliterator<T> source;
public Wrapper(Spliterator<T> source) {
this.source = source;
}
@Override
public boolean tryAdvance(Consumer<? super T> action) {
try {
return source.tryAdvance(action);
}
catch(XmlParseException ex) {
throw new CustomRuntimeException(ex);
}
}
@Override
public void forEachRemaining(Consumer<? super T> action) {
try {
source.forEachRemaining(action);
}
catch(XmlParseException ex) {
throw new CustomRuntimeException(ex);
}
}
@Override public Spliterator<T> trySplit() {
Spliterator<T> srcPrefix = source.trySplit();
return srcPrefix == null? null: new Wrapper<>(srcPrefix);
}
@Override public long estimateSize() { return source.estimateSize(); }
@Override public int characteristics() { return source.characteristics(); }
@Override public Comparator<? super T> getComparator(){return source.getComparator();}
}
Run Code Online (Sandbox Code Playgroud)
它保留原始的所有属性,Spliterator并仅转换迭代期间抛出的异常.
那你可以像使用它一样
protected Stream<T> parseFile(File file) {
Stream<T> s = parser.parse();
return StreamSupport.stream(new Wrapper<>(s.spliterator()), s.isParallel())
.onClose(s::close);
}
Run Code Online (Sandbox Code Playgroud)
呼叫者不应忘记正确关闭流:
ResultType result;
try(Stream<T> s = parseFile(file)) {
result = s.
// other intermediate ops
// terminal operation
}
Run Code Online (Sandbox Code Playgroud)
要么
ResultType result;
try(Stream<T> s = parseFile(file)) {
result = s.
// other intermediate ops
// terminal operation
}
finally {
// other cleanup actions
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
140 次 |
| 最近记录: |