如何连接两个可选<;字符串>;在Java8中使用分隔符
我有两个如何连接两个可选<;字符串>;在Java8中使用分隔符,java,java-8,optional,Java,Java 8,Optional,我有两个可选的字符串,name1和name2。我想加入这两个选项,这样结果也是可选的: 如果其中一个为非空,则结果应为非空名称 如果两者都非空,我希望结果与分隔符和合并 如果两者都为空,则结果应为空可选 我的尝试是: StringBuilder sb = new StringBuilder(); name1.ifPresent(sb::append); name2.ifPresent(s -> { if (sb.length() > 0) { sb.appen
可选的字符串,name1
和name2
。我想加入这两个选项,这样结果也是可选的:
如果其中一个为非空,则结果应为非空名称
如果两者都非空,我希望结果与分隔符和
合并
如果两者都为空,则结果应为空可选
我的尝试是:
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()));
StringBuilder sb=新建StringBuilder();
名称1.如果存在(sb::追加);
名称2.如果存在(s->{
如果(sb.length()>0){
某人附加(“及”);
}
某人追加;
}
Optional joinedOpt=Optional.ofNullable(Strings.emptyToNull(sb.toString());
这是可行的,但看起来很难看,也不太实用
PS:有一个类似的答案,但被接受的答案是错误的。具体地说,如果name1
为空而name2
为空,它将返回一个空的可选值。Java 1.9中可能的解决方案是
Optional<String> name1 = Optional.of("x");
Optional<String> name2 = Optional.of("y");
String s = Stream.concat(name1.stream(), name2.stream()).collect(Collectors.joining(" AND "));
System.out.println(s);
这里是一个流式解决方案,它过滤存在的可选
元素,然后提取元素并使用内置收集器加入其余元素。然后它测试结果是否为空,以返回空的可选
它接受一个列表
的可选
s,因此它涵盖了比两个元素更一般的情况
public Optional<String> optionalJoin(List<Optional<String>> strings) {
String result = strings.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.joining(" AND "));
return result.isEmpty() ? Optional.empty() : Optional.of(result);
}
public可选选项连接(列表字符串){
字符串结果=strings.stream()
.filter(可选::isPresent)
.map(可选::get)
.收款(收款人加入(“和”);
返回result.isEmpty()?Optional.empty():Optional.of(result);
}
一个无流的衬里,但不是特别优雅:
public static Optional<String> concat(Optional<String> name1, Optional<String> name2) {
return Optional.ofNullable(name1.map(s1 -> name2.map(s2 -> s1 + " AND " + s2).orElse(s1)).orElse(name2.orElse(null)));
}
public static void main(String[] args) {
System.out.println(concat(Optional.of("A"), Optional.of("B")));
System.out.println(concat(Optional.of("A"), Optional.empty()));
System.out.println(concat(Optional.empty(), Optional.of("B")));
System.out.println(concat(Optional.empty(), Optional.empty()));
}
public静态可选concat(可选名称1,可选名称2){
返回可选的.ofNullable(name1.map(s1->name2.map(s2->s1+”和“+s2).orElse(s1)).orElse(name2.orElse(null));
}
公共静态void main(字符串[]args){
系统输出打印LN(concat(可选的of(“A”)、可选的of(“B”));
System.out.println(concat(可选的.of(“A”),可选的.empty());
System.out.println(concat(Optional.empty(),Optional.of(“B”)));
System.out.println(concat(可选的.empty(),可选的.empty());
}
一种解决方案是流式处理和reduce()
:
Optional joinedOpt=Stream.of(name1,name2)
.filter(可选::isPresent)
.map(可选::get)
.减少((a,b)->a+”和“+b);
您可以按照其他人的建议,用Java 9或番石榴替换过滤器/映射组合。有时,尝试使用可选(或流
)实现功能只会模糊您试图在代码中表达的内容
对我来说,这里的主要思想是,如果两个值都存在,那么它们应该用“AND”连接起来。下面是一个重点:
Optional<String> joinedOpt;
if (name1.isPresent() && name2.isPresent()) {
joinedOpt = Optional.of(name1.get() + " AND " + name2.get());
} else {
joinedOpt = name1.isPresent() ? name1 : name2;
}
可选连接点;
if(name1.isPresent()&&name2.isPresent()){
joinedOpt=Optional.of(name1.get()+”和“+name2.get());
}否则{
joinedOpt=name1.isPresent()?name1:name2;
}
我可能误解了他的信息,但这种方法的灵感来源于他在帮助设计可选时所做的选择。他使用收集器设计了略微不同的风格。加入:
Optional<String> result = Optional.of(
Stream.of(so1, so2)
.filter(Optional::isPresent)
.map(Optional::get)
.collect( Collectors.joining(" AND ") )
).filter( s -> !s.isEmpty() );
Optional result=Optional.of(
(so1、so2)的流量
.filter(可选::isPresent)
.map(可选::get)
.收集(收集器。连接(“和”))
).filter(s->!s.isEmpty());
我喜欢收集器。加入是因为Java streams可以潜在地重用单个StringBuilder类,而不是在执行+
操作时创建一个新的类。接近公认的答案
Optional<String> joinedOpt = Stream.of(name1, name2)
.flatMap(x -> x.map(Stream::of).orElse(null))
.reduce((a, b) -> a + " AND " + b);
Optional joinedOpt=Stream.of(name1,name2)
.flatMap(x->x.map(Stream::of).orElse(null))
.减少((a,b)->a+”和“+b);
或者在java-9中:
Optional<String> joinedOpt = Stream.of(name1, name2)
.flatMap(Optional::stream)
.reduce((a, b) -> a + " AND " + b);
Optional joinedOpt=Stream.of(name1,name2)
.flatMap(可选::流)
.减少((a,b)->a+”和“+b);
Nice!我想在Java中也可以用番石榴做同样的事情8@spinlok是的,如果番石榴是可用的,那么您可以进行排序。当两者都为空时,这不会返回空的可选项。@SleimanJneidi还有为什么会有orElseGet
而不是orElse(Stream.empty())
,这不像创建一个空流是昂贵的。请同时假设代码工作正常,您可能希望以更完整的方式编写您的示例,并在上征求评论。请务必先阅读,因为那里有些事情的处理方式不同!我花了一些时间来理解此解决方案,因此它在从某种意义上说,它确实起到了作用,但在我看来,理解起来有点费时,所以可读性很低。当我说可读性时,我的意思是“另一个人”可以看着代码说“啊,这就是它的功能”。但这可能只是我…@Aominè。我认为这只是个人观点。对我来说,这看起来是一个干净易读的解决方案。可能是因为过去的MapReduce工作。我唯一的意见是在每个元素上创建太多中间StringBuilder
对象,而不是在使用收集器时可能重用单个对象。jOing
@tsolakp是的,这是一个基于意见的评论。顺便说一句,我喜欢这个答案;-)。无论如何,我唯一的意见是在每个元素上创建太多的中间StringBuilder对象,而不是在使用Collectors.joining时可能重用单个对象,请记住,我们最多有2个(加上“和”)字符串对象,因此可能不值得使用StringBuilder
。串联总是在后台使用StringBuilder。但是这个减少最多只能调用一次。@shmosel不总是,startin
Optional<String> result = Optional.of(
Stream.of(so1, so2)
.filter(Optional::isPresent)
.map(Optional::get)
.collect( Collectors.joining(" AND ") )
).filter( s -> !s.isEmpty() );
Optional<String> joinedOpt = Stream.of(name1, name2)
.flatMap(x -> x.map(Stream::of).orElse(null))
.reduce((a, b) -> a + " AND " + b);
Optional<String> joinedOpt = Stream.of(name1, name2)
.flatMap(Optional::stream)
.reduce((a, b) -> a + " AND " + b);