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


当前回答

如果你想存储这个值:

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

其他回答

另一个解决方案是:

下面是它的用法:

    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 */

你不能在ifPresent之后调用orElse,原因是,orElse是在可选对象上调用的,而ifPresent返回void。所以实现的最好方法是ifpresenttorelse。 它可以是这样的:

op.ifPresentOrElse( 
            (value) 
                -> { System.out.println( 
                         "Value is present, its: "
                         + value); }, 
            () 
                -> { System.out.println( 
                         "Value is empty"); }); 

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

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

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

对我来说,@Dane White的答案是OK的,首先我不喜欢使用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();
    }
}

Then可用作:

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个东西:

可以很容易地定义一个对象存在之前的功能。 没有为每个可选对象创建对象引用,只有一个,所以内存比GC更少。 它正在实现消费者,以便更好地与其他组件一起使用。

顺便说一下,现在它的名字更有描述性它实际上是Consumer<Optional<?>>