从Java返回可选的ifPresent()

时间:2019-02-26 03:34:14

标签: java java-8 optional

我知道您无法从ifPresent()返回,因此此示例不起作用:

public boolean checkSomethingIfPresent() {
    mightReturnAString().ifPresent((item) -> {
        if (item.equals("something")) {
            // Do some other stuff like use "something" in API calls
            return true; // Does not compile
        }
    });
    return false;
}

mightReturnAString() 可以在哪里返回有效的字符串或空的可选字符。我所做的工作是:

public boolean checkSomethingIsPresent() {
    Optional<String> result = mightReturnAString();

    if (result.isPresent()) {
        String item = result.get();
        if (item.equals("something") {
            // Do some other stuff like use "something" in API calls
            return true;
        }
    }
    return false;
}

更长,与仅检查空值没有什么不同。我觉得使用Optional必须有更简洁的方式。

5 个答案:

答案 0 :(得分:1)

如何映射到布尔值?

public boolean checkSomethingIfPresent() {
    return mightReturnAString().map(item -> {
        if (item.equals("something")) {
            // Do some other stuff like use "something" in API calls
            return true; // Does not compile
        }
        return false; // or null
    }).orElse(false);
}

答案 1 :(得分:1)

我想您只是在寻找filter,然后检查是否存在:

return result.filter(a -> a.equals("something")).isPresent();

答案 2 :(得分:1)

虽然@nullpointer和@Ravindra展示了如何将Optional与另一个条件合并,但是您必须做更多的工作才能调用API并按照问题中的要求进行其他操作。在我看来,以下内容看起来很容易阅读和简洁:

private static boolean checkSomethingIfPresent() {
    Optional<String> str = mightReturnAString();
    if (str.filter(s -> s.equals("something")).isPresent()) {
        //call APIs here using str.get()
        return true;
    }
    return false;
}

更好的设计是链接方法:

private static void checkSomethingIfPresent() {
    mightReturnFilteredString().ifPresent(s -> {
        //call APIs here
    });
}

private static Optional<String> mightReturnFilteredString() {
    return mightReturnAString().filter(s -> s.equals("something"));
}

private static Optional<String> mightReturnAString() {
    return Optional.of("something");
}

答案 3 :(得分:0)

理想的解决方案是“命令-查询分离”:如果存在字符串,则为该字符串创建一个方法(命令)。还有另一种方法(查询)来告诉您它是否在那里。

但是,我们没有一个理想的世界,永远不可能有完美的解决方案。如果在您的情况下无法将命令和查询分开,则我的想法是由shmosel已经提出的想法:映射到boolean。详细而言,我将使用filter而不是内部的if语句:

public boolean checkSomethingIfPresent() {
    return mightReturnAString().filter(item -> item.equals("something"))
            .map(item -> {
                // Do some other stuff like use "something" in API calls
                return true; // (compiles)
            })
            .orElse(false);
}

我不喜欢呼叫链具有副作用,通常不会出现这种副作用,除非是ifPresentifPresentOrElse(当然还有orElseThrow

如果我们坚持使用ifPresent来使副作用更明显,则有可能:

    AtomicBoolean result = new AtomicBoolean(false);
    mightReturnAString().filter(item -> item.equals("something"))
            .ifPresent(item -> {
                // Do some other stuff like use "something" in API calls
                result.set(true);
            });
    return result.get();

我将AtomicBoolean用作结果的容器,因为不允许我们在lambda中将其分配给原始boolean。我们不需要它的原子性,但是也没有害处。

链接: Command–query separation在Wikipedia上

答案 4 :(得分:0)

顺便说一句,如果您真的想从 Optional 中获取价值,请使用:

Optional<User> user = service.getCurrentUset();

return user.map(User::getId);