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


当前回答

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

其他回答

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<?>>

如果你想存储这个值:

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

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

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

问题是:

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