在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()将继续执行。


当前回答

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

其他回答

如果你想存储这个值:

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

另一种选择是:

System.out.println(opt.map(o -> "Found")
                      .orElse("Not found"));

但我不认为它能提高可读性。

或者像Marko建议的那样,使用三元操作符:

System.out.println(opt.isPresent() ? "Found" : "Not found");

问题是:

optional
  .map(object -> {
    System.out.println("If present.");
    return null;
  })
  .orElseGet( () -> {
    System.out.println("If empty.");
    return null;
  });

map()是否将第一个函数返回的null转换为empty();然后返回empty()。当它返回empty()时,它提示调用第二个函数。注意,orElseGet()不会将第二个函数返回的null转换为empty(),因此它将返回null。

参见map()的实现:

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Optional.ofNullable(mapper.apply(value));
    }
}

和orElseGet()的实现:

public T orElseGet(Supplier<? extends T> other) {
    return value != null ? value : other.get();
}

因此执行时:

if optional.isPresent(),系统将打印if present。,则If为空。,表达式将求值为null。 if !optional.isPresent(),系统将打印if为空。,表达式将求值为null。


如果提供给map()的函数返回任何其他值-任何其他值-代码将如您所期望的那样工作,如果isPresent()则执行提供给map()的函数,如果!isPresent()则执行提供给orElseGet()的函数:

例如,这个:

optional
  .map(data -> {
    System.out.println("If present.");
    return 0;
  })
  .orElseGet( () -> {
    System.out.println("If empty.");
    return 0;
  });

当执行:

if optional.isPresent(),系统将打印if present。,表达式的值为0。 if !optional.isPresent(),系统将打印if为空。,表达式的值为0。

如果是你的特定情况,我建议你的insert和update方法返回持久化对象,或者持久化对象的id,或者类似有用的东西;然后你可以使用类似这样的代码:

final Object persist = optional
  .map(object -> {
    System.out.println("If present.");
    return update(object);
  })
  .orElseGet( () -> {
    System.out.println("If empty.");
    return insert(new Object());
  });

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

另一个解决方案是:

下面是它的用法:

    final Opt<String> opt = Opt.of("I'm a cool text");
    opt.ifPresent()
        .apply(s -> System.out.printf("Text is: %s\n", s))
        .elseApply(() -> System.out.println("no text available"));

或者如果你。如果相反的用例是真的:

    final Opt<String> opt = Opt.of("This is the text");
    opt.ifNotPresent()
        .apply(() -> System.out.println("Not present"))
        .elseApply(t -> /*do something here*/);

这些是成分:

稍微修改了函数界面,只是为了“elseApply”方法 可选增强 一点点卷曲:-)

“美化”增强的功能界面。

@FunctionalInterface
public interface Fkt<T, R> extends Function<T, R> {

    default R elseApply(final T t) {
        return this.apply(t);
    }

}

和用于增强的Optional包装器类:

public class Opt<T> {

    private final Optional<T> optional;

    private Opt(final Optional<T> theOptional) {
        this.optional = theOptional;
    }
    
    public static <T> Opt<T> of(final T value) {
        return new Opt<>(Optional.of(value));
    }

    public static <T> Opt<T> of(final Optional<T> optional) {
        return new Opt<>(optional);
    }
    
    public static <T> Opt<T> ofNullable(final T value) {
        return new Opt<>(Optional.ofNullable(value));
    }
    
    public static <T> Opt<T> empty() {
        return new Opt<>(Optional.empty());
    }

    private final BiFunction<Consumer<T>, Runnable, Void> ifPresent = (present, notPresent) -> {
        if (this.optional.isPresent()) {
            present.accept(this.optional.get());
        } else {
            notPresent.run();
        }
        return null;
    };

   private final BiFunction<Runnable, Consumer<T>, Void> ifNotPresent = (notPresent, present) -> {
        if (!this.optional.isPresent()) {
            notPresent.run();
        } else {
            present.accept(this.optional.get());
        }
        return null;
    };

    public Fkt<Consumer<T>, Fkt<Runnable, Void>> ifPresent() {
        return Opt.curry(this.ifPresent);
    }

    public Fkt<Runnable, Fkt<Consumer<T>, Void>> ifNotPresent() {
        return Opt.curry(this.ifNotPresent);
    }

    private static <X, Y, Z> Fkt<X, Fkt<Y, Z>> curry(final BiFunction<X, Y, Z> function) {
        return (final X x) -> (final Y y) -> function.apply(x, y);
    }
}

这应该可以解决问题,并且可以作为处理此类需求的基本模板。

The basic idea here is following. In a non functional style programming world you would probably implement a method taking two parameter where the first is a kind of runnable code which should be executed in case the value is available and the other parameter is the runnable code which should be run in case the value is not available. For the sake of better readability, you can use curring to split the function of two parameter in two functions of one parameter each. This is what I basically did here.

提示:Opt还提供了另一个用例,在该用例中,您希望执行一段代码,以防该值不可用。这也可以通过Optional.filter.stuff完成,但我发现这更可读。

希望有帮助!

额外的信息:

还有另一种表达if then else的方法:

public static <X, Y> Function<Predicate<X>, Function<Function<X, Y>, Function<Function<X, Y>, Y>>> ifThenElse(X input) {
  return (final Predicate<X> pred) -> (final Function<X, Y> ifPresent) -> (final Function<X, Y> ifNotPresent) -> pred.test(input) ? ifPresent.apply(input) : ifNotPresent.apply(input);
}

这样你就可以说:

final String result = ifThenElse("fancy")
  .apply(input -> input.contains("fancy")) /* test      */
  .apply(input -> input.toUpperCase())     /* if-case   */
  .apply(input -> input.toLowerCase());    /* else-case */