Java 8 的 Optional.ifPresent 和 if-not-Present 的功能风格?

在Java 8中,我想对一个对象做一些事情,如果它存在,我想做另一件事,如果它不存在。Optional

if (opt.isPresent()) {
  System.out.println("found");
} else {
  System.out.println("Not found");
}

不过,这不是一种“功能性风格”。

Optional有一个方法,但我无法链接一个方法。ifPresent()orElse()

因此,我不能写:

opt.ifPresent( x -> System.out.println("found " + x))
   .orElse( System.out.println("NOT FOUND"));

在回复@assylias,我认为不适用于以下情况:Optional.map()

opt.map( o -> {
  System.out.println("while opt is present...");
  o.setProperty(xxx);
  dao.update(o);
  return null;
}).orElseGet( () -> {
  System.out.println("create new obj");
  dao.save(new obj);
  return null;
});

在这种情况下,当 存在时,我更新其属性并保存到数据库中。当它不可用时,我创建一个新的并保存到数据库。optobj

请注意,在两个 lambda 中,我必须返回 。null

但是,当存在时,将执行两个 lambda。 将更新,并且新对象将保存到数据库 。这是因为在第一个 lambda 中。并将继续执行。optobjreturn nullorElseGet()


答案 1

如果您使用的是Java 9+,则可以使用ifPresentOrElse()方法:

opt.ifPresentOrElse(
   value -> System.out.println("Found: " + value),
   () -> System.out.println("Not found")
);

答案 2

对我来说,@Dane White的答案是可以的,首先我不喜欢使用,但我找不到任何替代品。Runnable

这里另一个我更喜欢的实现:

public class OptionalConsumer<T> {
    private Optional<T> optional;

    private OptionalConsumer(Optional<T> optional) {
        this.optional = optional;
    }

    public static <T> OptionalConsumer<T> of(Optional<T> optional) {
        return new OptionalConsumer<>(optional);
    }

    public OptionalConsumer<T> ifPresent(Consumer<T> c) {
        optional.ifPresent(c);
        return this;
    }

    public OptionalConsumer<T> ifNotPresent(Runnable r) {
        if (!optional.isPresent()) {
            r.run();
        }
        return this;
    }
}

然后:

Optional<Any> o = Optional.of(...);
OptionalConsumer.of(o).ifPresent(s -> System.out.println("isPresent " + s))
                .ifNotPresent(() -> System.out.println("! isPresent"));

更新 1:

上面的解决方案对于传统的开发方式,当你有价值并想要处理它,但如果我想定义功能和执行将会是什么,请检查下面的增强功能;

public class OptionalConsumer<T> implements Consumer<Optional<T>> {
private final Consumer<T> c;
private final Runnable r;

public OptionalConsumer(Consumer<T> c, Runnable r) {
    super();
    this.c = c;
    this.r = r;
}

public static <T> OptionalConsumer<T> of(Consumer<T> c, Runnable r) {
    return new OptionalConsumer(c, r);
}

@Override
public void accept(Optional<T> t) {
    if (t.isPresent()) {
        c.accept(t.get());
    }
    else {
        r.run();
    }
}

然后可以用作:

Consumer<Optional<Integer>> c = OptionalConsumer.of(
    System.out::println, 
    () -> System.out.println("Not fit")
);

IntStream.range(0, 100)
    .boxed()
    .map(i -> Optional.of(i)
    .filter(j -> j % 2 == 0))
    .forEach(c);

在这个新代码中,你有3件事:

  1. 可以在存在对象之前轻松定义功能。
  2. 不为每个可选创建对象引用,只有一个,你的内存比更少的GC少。
  3. 它正在实现消费者,以便更好地与其他组件一起使用。

顺便说一句,现在它的名字更具描述性,它实际上是消费者<选择<>>