我遇到这个简单的事情有困难。我有一个方法返回Optional<TypeA>
:
public Optional<TypeA> getFirst() {
return set.stream().filter(it -> it.getStatus() == SUCCESS).findFirst(); // set is a Set<TypeA>
}
...然后我从以下地方打电话:
public boolean hasFirst() {
return types.parallelStream() // types is a List<TypeB> that has a Set<TypeA>
.filter(it -> it.getTotalAmount() > 0)
.map(TypeA::getFirst)
.findFirst() // this can return an Optional[Optional.empty]
.isPresent();
}
问题是,Optional
空Optional
正在按预期返回true
,所以我不知道如何正确使用这个!{/ p>
任何线索?
答案 0 :(得分:3)
您可以使用Optional#flatMap
来解开&#39;内在的选择:
public boolean hasFirst() {
return types.parallelStream()
.filter(it -> it.getTotalAmount() > 0)
.map(TypeA::getFirst)
.findFirst() // return Optional[Optional.empty]
.flatMap(i -> i) // <---
.isPresent(); // true
}
如果存在值,则将提供的Optional-bearing映射函数应用于该函数,返回该结果,否则返回空的Optional。
答案 1 :(得分:3)
使用.findFirst().isPresent()
是一种常见的反模式。如果您只想知道是否匹配,如果您打算使用并行流,则无需询问第一个,尤其是,其中对于第一场比赛而不是任何比赛可能会有明显的性能缺陷。所以findAny
会更受欢迎,但是当你只想知道是否匹配时,没有必要要求一个价值:
public boolean hasFirst() {
return types.parallelStream() // types is a List<TypeB> that has a Set<TypeA>
.filter(it -> it.getTotalAmount() > 0)
.anyMatch(obj -> obj.getFirst().isPresent());
}
目前尚不清楚,如果types
是TypeB
个实例的列表,而getFirst()
是TypeA
中声明的方法,原始代码应该如何工作, TypeA::getFirst
表示,但是,我想,你得到的照片......
我建议您还将方法hasFirst()
重命名为hasAny()
。当然,具有任何匹配元素的集合也将具有第一个,但是关注“第一”的集合会产生误导,特别是因为TypeA
元素是在Set
中,这通常意味着根本没有定义的顺序。
答案 2 :(得分:1)
要将Optional<Optional<Foo>>
折叠为Optional<Foo>
,您可以使用orElse
,因此:
Optional<Optional<Integer>> opt = Optional.of(Optional.empty()); // Your case
Optional<Integer> collapsedOpt = opt.orElse(Optional.empty()); // Will be empty if original is empty or Optional.of(empty).
因此,对于您的示例,您可以在流调用中添加.orElse:
public boolean hasFirst() {
return types.parallelStream()
.filter(it -> it.getTotalAmount() > 0)
.map(TypeA::getFirst)
.findFirst() // return Optional[Optional.empty]
.orElse(Optional.empty()) // Now Optional.empty if was originally empty
.isPresent(); // true
}