如果存在Java 8的Optional,则返回方法

时间:2017-07-18 15:14:59

标签: java lambda java-8 return optional

在Java 8中,如果Optional存在,是否有办法强制方法返回? 我猜这个答案是否定的。但是,如何避免在以下代码中使用isPresent()get()

public Bar myMethod(){
    if(condition){
        Optional<Foo> foo = getOptionalFoo();
        if(foo.isPresent()){
            return foo.get().getBar();
        }
    }

    return getOtherBar();
}

一种解决方案是写:

public Bar myMethod(){
    if(condition){
        return getOptionalFoo()
                .map(Foo::getBar)
                .orElseGet(() -> getOtherBar());
    }

    return getOtherBar();
}

但这似乎不是一个好主意,因为现在我们写了两次调用getOtherBar。有没有办法避免这种情况?

编辑:我也想过

public Bar myMethod(){
    //Or a ternary operator but there are hard to read when they make long lines
    Optional<Foo> foo;
    if(condition){
        foo = getOptionalFoo();
    } else {
        foo = Optional.empty();
    }

    return foo.map(Foo::getBar)
        .orElseGet(() -> getOtherBar());
}

但问题在于我们为它创建了一个无用的空Optional和链方法。如果在99%的情况下不满足条件,这会使其效率远低于原始代码(特别是如果我们有多个map()filter())。

注意:我给出了一个基本的例子,实际上在我们的代码中我们有更多的条件依赖于其他调用的结果(取决于foo)。

3 个答案:

答案 0 :(得分:3)

这个怎么样?下面代码的形式更强可读比你的更强,因为如果不满足conditiongetOtherBar()还需要额外的map上的操作(orElseGet&amp; Optional)。

public Bar myMethod() {
    Optional<Foo> source = condition ? getFoo() : Optional.empty();

    return source.map(Foo::getBar)
                 .orElseGet(this::getOtherBar);
}

但是,如果像上面那样有很多重复,那么你可以通过提取方法来释放自己,例如:

private Optional<Foo> foo(){
    return  condition ? getFoo() : Optional.empty();
}

public Bar myMethod() {
    return foo().map(Foo::getBar).orElseGet(this::getOtherBar);
}

public Other otherMethod() {
    return foo().map(Foo::getOther).orElseGet(this::getOther);
}

答案 1 :(得分:3)

什么是condition?由于它位于实例方法中,因此它必须是一个条件,具体取决于实例的状态。为简单起见,假设这是您班级的一个领域,那么您可以编写

public Bar myMethod() {
    return Optional.of(this)
        .filter(obj -> obj.condition)
        .flatMap(ClassContainingMyMethod::getFoo)
        .map(Foo::getBar)
        .orElseGet(this::getOtherBar);
}

如果getFoo()不贵并且没有副作用,即使您不打算使用其结果,也可以接受始终调用它,具体取决于condition。这将简化代码

public Bar myMethod() {
    return getFoo()
        .filter(foo -> condition)
        .map(Foo::getBar)
        .orElseGet(this::getOtherBar);
}

请注意,原始代码存在语义差异。当getBar返回null时,原始代码会返回null,而使用带有Optional.map结果的函数的getBar()的所有代码都将返回调用{ {1}}。

答案 2 :(得分:2)

一旦你进入Optional心态,并使用三元运算符来处理你的病情,这很容易就会崩溃。

public Bar myMethod(){
    return ( condition ? getOptionalFoo() : Optional.<Foo> empty())
         .map(f -> f.getBar())
         .orElseGet(() -> getOtherBar())
}