我有两个 Optional
字符串, name1
和 name2
. 我想加入这两个,结果也是一个可选的:
-
如果其中任何一个非空,则结果应为非空名称 .
-
如果两者都非空,我希望结果与分隔符
AND
连接 . -
如果两者都为空,结果应为空
Optional
我的尝试:
StringBuilder sb = new StringBuilder();
name1.ifPresent(sb::append);
name2.ifPresent(s -> {
if (sb.length() > 0) {
sb.append(" AND ");
}
sb.append(s);
}
Optional<String> joinedOpt = Optional.ofNullable(Strings.emptyToNull(sb.toString()));
这很有效,但看起来很难看,而且功能不是很好 .
PS:有一个类似的question但接受的答案是错误的 . 具体来说,如果 name1
为空且 name2
不为,则返回空的可选项 .
7 回答
一种解决方案是流和
reduce()
:如其他人所建议的那样,随意用Java 9或Guava替换filter / map组合 .
Java 1.9中可能的解决方案是
使用Java 1.8,您无法从Optional到Stream . 但是,您可以非常轻松地将此类转换添加到Java 1.8 .
现在您可以使用
of
方法连接两个流 .现在,如果没有结果,为了得到一个空的
Optional
,你可以将结果包装成一个Optional并做一个简单的过滤器 .使用
Collectors.joining
略有不同的味道:我喜欢的是
Collectors.joining
是Java流可以重用单个StringBuilder类而不是在执行+
操作时创建一个新类 .有时,尝试使用
Optional
(或Stream
)功能只会模糊您在代码中尝试表达的内容 .对我来说,这里的主要想法是,如果两个值都存在,它们应该与“AND”连接 . 以下是对此的关注:
我可能会误解他的信息,但这种方法的灵感来自Stuart Marks' answer to a similiar question,,他在his Devoxx talk中更深入地讨论了他在帮助设计
Optional
时做出的选择 .接近接受的答案
或者在java-9中:
这是一个流式解决方案,它过滤那些存在的
Optional
,然后提取元素并使用内置的收集器来连接其余的元素 . 然后它测试结果是否为空,返回空Optional
.它接受
List
的Optional
,所以它涵盖了一个更普遍的情况而不仅仅是两个元素 .没有Streams的单行,但不是特别优雅: