Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 强制终端操作_Java_Java Stream_Optional_Java 9 - Fatal编程技术网

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好吧,我不知道。我添加标签。