在Java 8中,我想对一个可选对象做一些事情,如果它是存在的,并做另一件事,如果它不存在。

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;
});

在本例中,当出现opt时,我更新它的属性并保存到数据库。当它不可用时,我创建一个新的obj并保存到数据库。

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

但是当opt存在时,两个lambdas都将被执行。Obj将被更新,一个新的对象将被保存到数据库中。这是因为在第一个lambda中返回null。orElseGet()将继续执行。


当前回答

另一种解决方案是使用如下所示的高阶函数

opt.<Runnable>map(value -> () -> System.out.println("Found " + value))
   .orElse(() -> System.out.println("Not Found"))
   .run();

其他回答

如果你想存储这个值:

Pair.of<List<>, List<>> output = opt.map(details -> Pair.of(details.a, details.b))).orElseGet(() -> Pair.of(Collections.emptyList(), Collections.emptyList()));

没有一个很好的方法可以打破常规。如果你想在常规的基础上使用更干净的语法,那么你可以创建一个实用工具类来帮助你:

public class OptionalEx {
    private boolean isPresent;

    private OptionalEx(boolean isPresent) {
        this.isPresent = isPresent;
    }

    public void orElse(Runnable runner) {
        if (!isPresent) {
            runner.run();
        }
    }

    public static <T> OptionalEx ifPresent(Optional<T> opt, Consumer<? super T> consumer) {
        if (opt.isPresent()) {
            consumer.accept(opt.get());
            return new OptionalEx(true);
        }
        return new OptionalEx(false);
    }
}

然后你可以在其他地方使用静态导入来获得与你想要的语法相近的语法:

import static com.example.OptionalEx.ifPresent;

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

Java 9引入了

如果存在一个值,则使用该值执行给定的操作,否则执行给定的基于空的操作。

参见Java 8备忘单中的优秀可选选项。

它为大多数用例提供了所有答案。

下面是简短的总结

ifPresent() -设置Optional时执行一些操作

opt.ifPresent(x -> print(x)); 
opt.ifPresent(this::print);

filter() -拒绝(过滤掉)某些可选值。

opt.filter(x -> x.contains("ab")).ifPresent(this::print);

Map() -如果存在则转换值

opt.map(String::trim).filter(t -> t.length() > 1).ifPresent(this::print);

orElse()/orElseGet() - turning empty可选,默认T

int len = opt.map(String::length).orElse(-1);
int len = opt.
    map(String::length).
    orElseGet(() -> slowDefault());     //orElseGet(this::slowDefault)

orElseThrow() -惰性抛出空异常可选

opt.
filter(s -> !s.isEmpty()).
map(s -> s.charAt(0)).
orElseThrow(IllegalArgumentException::new);

如果你只能使用Java 8或更低版本:

1)如果你没有弹簧数据,到目前为止最好的方法是:

opt.<Runnable>map(param -> () -> System.out.println(param))
      .orElse(() -> System.out.println("no-param-specified"))
      .run();

现在我知道对某些人来说,它不是那么可读,甚至很难理解,但对我个人来说,它看起来还不错,我想不出另一种流畅的方法来处理这种情况。

2)如果你足够幸运,你可以使用弹簧数据,最好的方法是 可选# ifPresentOrElse:

Optionals.ifPresentOrElse(opt, System.out::println,
      () -> System.out.println("no-param-specified"));

如果你能使用Java 9,你绝对应该使用:

opt.ifPresentOrElse(System.out::println,
      () -> System.out.println("no-param-specified"));

如果你使用Java 9+,你可以使用ifPresentOrElse()方法:

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