Functional programming 如何使用delimeter连接字符串,delimeter以java8函数式在内部级别连接字符串
我有Functional programming 如何使用delimeter连接字符串,delimeter以java8函数式在内部级别连接字符串,functional-programming,java-8,java-stream,Functional Programming,Java 8,Java Stream,我有Map我的地图带结构: { "key1" : ["val1","val2","val3"] "key2" : ["val4","val5","val6"] "key3" : ["val7","val8"] } 我可以使用收集器将每个值与键联接。联接: val1-key1-val2-key1-val3 val4键2 val5键2 val6 val7键3 val8 但在全球范围内,我还需要将所有值合并到一个字符串中: "val1 key1 val2 key1 va
Map我的地图代码>带结构:
{
"key1" : ["val1","val2","val3"]
"key2" : ["val4","val5","val6"]
"key3" : ["val7","val8"]
}
我可以使用收集器将每个值与键联接。联接:
val1-key1-val2-key1-val3
val4键2 val5键2 val6
val7键3 val8
但在全球范围内,我还需要将所有值合并到一个字符串中:
"val1 key1 val2 key1 val3 key2 val4 key2 val5 key2 val6 key3 val7 key3 val8"
^ ^
其中值由右值中的键连接
是的,我可以以命令式的方式实现这一点,但我问我如何使用流api实现这一点。首先,应该强调的是,只有在定义了遭遇顺序的情况下,此请求才有意义,这不适用于普通的HashMap
和HashSet
对于具有稳定顺序的映射和集合,例如LinkedHashMap
,TreeMap
及其Set
对应项,如果我们可以使用以下内容,那就太好了:
String s=myMap.entrySet().stream()
.map(e -> e.getValue().stream().collect(
()->new StringJoiner(" "+e.getKey()+" "),StringJoiner::add, StringJoiner::merge))
.collect(()->new StringJoiner(""), StringJoiner::merge, StringJoiner::merge)
.toString();
但它不起作用,因为StringJoiner::merge
将使用左StringJoiner
的分隔符,而不是右分隔符
由于此行为是不可配置的,因此我们需要自己的StringJoiner变体
:
final class RightHandJoiner {
String separator;
StringBuilder content;
public RightHandJoiner(String sep) {
separator = sep;
}
public RightHandJoiner add(CharSequence next) {
if(content==null) content=new StringBuilder(next);
else content.append(separator).append(next);
return this;
}
public RightHandJoiner merge(RightHandJoiner next) {
if(next.content!=null) {
if(content==null) {
content=new StringBuilder(next.content);
separator=next.separator;
}
else content.append(next.separator).append(next.content);
}
return this;
}
public String toString() {
return content==null? "": content.toString();
}
}
这是有意简化的,只为您的任务服务,例如,它不支持非空前缀和后缀字符串。使用此类替换StringJoiner
,您将得到一个有效的解决方案:
String s=myMap.entrySet().stream()
.map(e -> e.getValue().stream()
.collect(() -> new RightHandJoiner(" "+e.getKey()+" "),
RightHandJoiner::add, RightHandJoiner::merge))
.collect(()->new RightHandJoiner(""), RightHandJoiner::merge, RightHandJoiner::merge)
.toString();
另一种方法是两次flatMap
,并构建键值字符串管道:
String s = myMap.entrySet().stream().flatMap(
e -> e.getValue().stream().flatMap(val -> Stream.of(e.getKey(), val))
).collect(Collectors.joining(" "));
System.out.println(s);
将为您提供:
键1 val1键1 val2键1 val3键2 val4键2 val5键2 val6键3 val7键3 val8
必须跳过第一个键字符串才能获得预期的输出
String s = myMap.entrySet().stream().flatMap(
e -> e.getValue().stream().flatMap(val -> Stream.of(e.getKey(), val))
).skip(1).collect(Collectors.joining(" "));
System.out.println(s);
val1键1 val2键1 val3键2 val4键2 val5键2 val6键3 val7键3 val8
您是否正在使用NavigableMap
和SortedSet
?发布命令式代码。这是一个优雅的解决方案,但不符合要求。看看问题中的预期结果。非常好,非常优雅,谢谢。我没想到流api会如此强大:)