在谓词中添加两个可选

Adding two Optionals in a Predicate

我必须在 Java 中写一个 Predicate,我可以在其中查询谓词的输入以获得两个 Optional<Integer> 对象。我必须根据两个 Optionals 的组合值 return true 或 false。除了检查 isPresent() 然后 get() 这些值并添加之外,还有其他更好的方法吗?

// Here assuming the comparingValue and integer1 and integer2 are all initialised with values.
// The isGreaterOrEqual function has an implementation.

int comparingValue;
Optional<Integer> integer1;
Optional<Integer> integer2;
if (integer1.isPresent() && integer2.isPresent()) 
    return isGreaterOrEqual(comparingValue, integer1.get() + integer2.get());
if (integer1.isPresent())
    return isGreaterOrEqual(comparingValue, integer1.get());
else if (integer2.isPresent()) 
    return isGreaterOrEqual(comparingValue, integer2.get());
else
    return false;

您可以将其缩短为:

if (integer1.isPresent() || integer2.isPresent()) {
    return compare(comparingValue, integer1.orElse(0) + integer2.orElse(0));
} else {
    return false;
}

更新,关于您对泛化的评论。 如果您想涵盖最一般的情况并且 有任何“默认值”(如 0)可以在比较之前与其他值“组合”(像 x + 0),那么你拥有的 IF 级联是你能得到的最好的。您可以使用 Optional's methods and convert it to a single expression, but in essence it' 重写它,仍然是具有 4 种情况的相同 IF 级联:

return 
  optValue1.map(
    // value1 is present
    value1 -> optValue2.map(
      // value2 is also present ==> combine and compare
      value2 -> compare(comparingValue, combine(value1, value2))
    ).orElseGet(
      // value2 is not present ==> use value1
      () -> compare(comparingValue, value1)
    )
  ).orElseGet(
    // value1 is not present
    optValue2.map(
      // value2 is present ==> use value2
      value2 -> compare(comparingValue, value2)
    ).orElse(
      // value2 is also not present ==> return default result
      false
    )
  );

“经典的”IF 级联对我来说似乎更具可读性:)

这是另一种方法:

return Stream.of(integer1, integer2)
    .flatMap(Optional::stream)
    .reduce((a, b) -> a + b)
    .map(t -> isGreaterOrEqual(comparingValue, t))
    .orElse(false);

不是不用isPresentget,而是流利的风格 → 感谢Hulk的评论,其实没有isPresentget.

在上述代码中发生了什么,我们构建了两个 Optional<Integer> 的流,然后:

  • 如果两个可选值都不为空,将它们的值相加并与 comparingValue
  • 进行比较
  • 如果正好有一个可选值非空,则与 comparingValue
  • 进行比较
  • 如果两者都为空,return false.

这种方法的优点是,如果需要,它允许添加更多的选项:

public boolean test(int comparingValue, Optional<Integer> optionalIntegers...) {
    Stream.of(optionalIntegers)

关于您对 'generalization' 的评论 — 当然,您不能将 + 运算符用于 String 以外的对象和数字类型的包装器 classes。如果我们假设您的 class 有一个具有以下签名的 merge 方法:

Money add(Money m1)

那么你只需要将reduce这一行替换为:

.reduce((a, b) -> a.add(b))

或者只是

.reduce(Money::add)

Java 8

对于 Java 8,您可以将 .flatMap(Optional::stream) 替换为

.filter(Optional::isPresent)
.map(Optional::get)

一切顺利。