在谓词中添加两个可选
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);
不是不用isPresent
和get
,而是流利的风格 → 感谢Hulk的评论,其实是没有isPresent
和get
.
在上述代码中发生了什么,我们构建了两个 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)
一切顺利。
我必须在 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);
不是不用 → 感谢Hulk的评论,其实是没有isPresent
和get
,而是流利的风格isPresent
和get
.
在上述代码中发生了什么,我们构建了两个 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)
一切顺利。