Java 强制终端操作
我有一个访问者,它返回一个泛型类型,以提供灵活的使用:Java 强制终端操作,java,java-stream,optional,java-9,Java,Java Stream,Optional,Java 9,我有一个访问者,它返回一个泛型类型,以提供灵活的使用: interface Base { default <T> Stream<T> accept(Visitor<T> visitor) { return visitor.visit(this).stream(); } } class Sub implements Base { <T> Stream<T> accept(Visitor<T&
interface Base {
default <T> Stream<T> accept(Visitor<T> visitor) {
return visitor.visit(this).stream();
}
}
class Sub implements Base {
<T> Stream<T> accept(Visitor<T> visitor) {
return Stream.concat(super.accept(visitor), visitor.visit(this).stream());
}
}
interface Visitor<T> {
default Optional<T> visit(Base base) {
return Optional.empty()
}
default Optional<T> visit(Sub sub){
return Optional.empty()
}
}
接口基础{
默认流接受(访问者){
return visitor.visit(this.stream();
}
}
类子实现基类{
流接受(访客){
return Stream.concat(super.accept(visitor)、visitor.visit(this.Stream());
}
}
界面访问者{
默认可选访问(基本){
返回可选的.empty()
}
默认可选访问(Sub){
返回可选的.empty()
}
}
我创建了一个访问对象流的方法:
<T> Stream<T> visitAll(Visitor<T> visitor) {
return getStream().flatMap(o -> o.accept(visitor));
}
Stream visitoll(访客){
返回getStream().flatMap(o->o.accept(visitor));
}
当访问者返回一个值时,此操作非常有效:
visitAll(new Visitor<Sub>() {
Optional<Sub> visit(Sub sub) {
return Optional.of(sub);
}
}).forEach(...);
visitAll(新访问者(){
可选访问(Sub){
返回可选。of(sub);
}
}).forEach(…);
当与不返回值的访问者一起使用时,会出现问题:
visitAll(new Visitor<Void>() {
Optional<Void> visit(Sub sub) {
// do something with sub
return Optional.empty();
}
});
visitAll(新访问者(){
可选访问(Sub){
//用潜艇做些什么
返回可选的.empty();
}
});
在这种情况下,流不会终止,因此访问不会发生
一种可能的解决方案是强制终端操作:
<T> Stream<T> visitAll(Visitor<T> visitor) {
return getStream()
.collect(Collectors.toList()).stream()
.flatMap(o -> o.accept(visitor));
}
Stream visitoll(访客){
返回getStream()
.collect(Collectors.toList()).stream()
.flatMap(o->o.accept(访问者));
}
另一种解决方案是始终使用以下值:
visitAll(new Visitor<Void>() {
Optional<Void> visit(Sub sub) {
// do something with sub
return Optional.empty();
}
}).findAny();
visitAll(新访问者(){
可选访问(Sub){
//用潜艇做些什么
返回可选的.empty();
}
}).findAny();
有没有一种更优雅的方法来强制在流上执行终端操作?或者,您是否可以建议一种替代设计来避免此问题?我将制作两个版本的
visitoll
,一个返回流,另一个终止流,但不返回任何内容
<T> Stream<T> visitAllStream(Visitor<T> visitor) {
return getStream().flatMap(o -> o.accept(visitor));
}
void visitAll(Visitor<?> visitor) {
getStream().forEach(o -> o.accept(visitor));
}
流访问流(访问者){
返回getStream().flatMap(o->o.accept(visitor));
}
无效访客(访客){
getStream().forEach(o->o.accept(visitor));
}
这样,只有在对结果执行进一步操作时,才能使用
visitAllStream
。您仍然必须确保在应该使用visitAll
时不使用visitAllStream
,但这会使错误更加明显。我认为让visit()
首先返回流是错误的。它违反了访问者必须访问对象的期望。返回一个列表,如果客户需要,让他们流式处理。@shmosel这是一个很好的建议-谢谢。我唯一关心的是,将有大量的列表对象创建的方式通过。虽然我想我不应该认为这比这个解决方案中创建的所有流都糟糕!我将试一试,看看是否还有其他建议提出。访问者。访问(此)
返回可选,您能告诉我如何从可选中生成流<代码>visitor.visit(this.stream()代码>错误。@Nikolas Optional从JDK9开始就有一个流方法。见class@Aomin好吧,我不知道。我添加标签。