为什么Java的Optional不会在ifPresent()中调用Consumer?

时间:2016-11-04 09:44:12

标签: java lambda java-8 optional consumer

public class TestSupplier {

Optional<Integer> opt1;

public static void main(String[] args) {
    // TODO Auto-generated method stub

    TestSupplier ts1 = new TestSupplier();

    ts1.opt1 = ts1.average(100,20,30,80);
    Consumer<Integer> cns1 = (x) -> x += 3;
    ts1.opt1.ifPresent(cns1);
    System.out.println(ts1.opt1.get());

}


private Optional<Integer> average(int... n1) {
    if (n1.length == 0) return Optional.empty();
    int sum = 0;
    for(int score: n1) sum += score; 
    return Optional.of(sum/n1.length);

}

}

当我运行代码时,结果为57(这是100,20,30,80平均值的正确结果)但是我创建了一个消费者,它应该将结果增加3 ...但它似乎不起作用。

有人可以帮助我吗?

2 个答案:

答案 0 :(得分:5)

Consumer动作实际上正在运行,但您提供的主体仅修改最终会丢失的本地实例。 ifPresent()方法仅用于执行副作用(动作)。

如果您要对Optional个实例所持有的值执行计算,请改用map()

ts1.opt1
  .map(x -> x + 3).orElseThrow(...)

get()实例上使用Optional时请务必小心。在您决定使用它之前,请查看orElseorElseGetorElseThrow

答案 1 :(得分:1)

Consumer<Integer> cns1 = new Consumer<Integer>() {
    public @Override void accept(Integer x) {
        // x is a local variable
        x += 3; // unboxing, adding, boxing 
        // the local variable has been changed
    }
};

就是这种情况,将lambda变成一个匿名类完全可以理解这一点。

这里最好的方法是

ts1.opt1.map(x -> x + 3).ifPresent(System.out::println);

您可以使用可变类的实例(例如AtomicInteger类):

Consumer<AtomicInteger> cns1 = x -> x.addAndGet(3);

在接受Consumer<AtomicInteger>后更改其状态(虽然不推荐,但请查看@pivovarit的答案)。

此外,该行

IntStream.of(100, 20, 30, 80).average().ifPresent(System.out::println);

可能会取代你所有的日常工作。