如果将旧用法转换为Optional.ifPresent()时出现问题

时间:2018-09-30 22:51:59

标签: java lambda java-8 optional

在将老式的用法转换为Optional.ifPresent时,我遇到了问题。这是该代码的先前版本。

State state = State.OK;
final Optional<Person> checkExistingPerson = checkIt();

if(checkExistingPerson.isPresent()) {
    Person person = checkExistingPerson.get();

    if("blah".equals(person.getName())) {
        state = State.DUPLICATE;
    } else {
        state = State.RESTORED;
    }

    return Member(person.getId(), state);
}

return Member(null, state);

这是Optional.ifPresent的用法

State state = State.OK;
final Optional<Person> checkExistingPerson = checkIt();

checkExistingPerson.ifPresent(person -> {

    if("blah".equals(person.getName())) {
        state = State.DUPLICATE;
    } else {
        state = State.NEW;
    }

    return Member(person.getId(), state);
});

return Member(null, state);

而且,这也是IntelliJ迫使我进行更改的屏幕截图。 enter image description here

针对我的问题,使用Optional的最佳方法是什么?谢谢!

4 个答案:

答案 0 :(得分:3)

  1. lambda内的外部变量必须为final
  2. ifPresent接受Consumer,因此它没有返回值,因此您不能使用return Member(person.getId(), state);(还要记住,您在lambda中,所以return是不会退出您的方法,而是退出lambda)。

map接受具有返回值的Function,因此您可以使用它代替ifPresent

通过在lambda内移动state并使用maporElseGet,这是重构代码的方式:

return checkExistingPerson.map(person -> {
    State state;

    if("blah".equals(person.getName())) {
        state = State.DUPLICATE;
    } else {
        state = State.NEW;
    }

    return Member(person.getId(), state);
})
.orElseGet(() -> Member(null, State.OK));

答案 1 :(得分:3)

您不能在lambda表达式中更改局部变量的值。此外,ifPresent无法返回值,因为其返回类型为void

相反,您应该使用Optional.map,它可以对Optional包裹的对象进行转换:

return checkExistingPerson
    .map(person -> new Member(
            person.getId(), 
            "blah".equals(person.getName()) ? State.DUPLICATE : State.RESTORED))
    .orElse(new Member(null, State.OK));

答案 2 :(得分:1)

如果要访问lambda表达式内的局部变量,则变量应为final或有效地为final,这意味着它们不能被修改here,也可以在lambda表达式内声明变量。 {1}}将使用ifPresent作为没有返回类型的参数,您使用Consumer将会使用map和根据@Loris的参数

答案 3 :(得分:1)

在内部方法中,如果未将外部变量定义为final,则不能引用它们,您可以像这样更改您的方法:

COUNT(DISTINCT user_id)