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


当前回答

另一个解决方案是:

下面是它的用法:

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

其他回答

问题是:

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

另一个解决方案是:

下面是它的用法:

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

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

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

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

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

假设你有一个列表,并且避免了isPresent()问题(与可选项相关),你可以使用.iterator(). hasnext()来检查是否不存在。