我有一串字符串:
Stream stream = ...;
我想构造一个字符串,将这些项连接起来作为分隔符.我这样做如下:
stream.collect(Collectors.joining(","));
现在我只想在有多个项目的情况下为此输出添加前缀[和后缀].例如:
> a
> [a,b]
> [a,b,c]
这可以在没有首先实现Stream< String>的情况下完成.到列表< String>然后检查List.size()== 1?在代码中:
public String format(Stream stream) {
List list = stream.collect(Collectors.toList());
if (list.size() == 1) {
return list.get(0);
}
return "[" + list.stream().collect(Collectors.joining(",")) + "]";
}
首先将流转换为列表然后再转换为流以便能够应用Collectors.joining(“,”)会感觉很奇怪.我认为循环遍历整个流(在Collectors.toList()期间完成)仅仅是为了发现是否存在一个或多个项目是不理想的.
我可以实现自己的收集器< String,String>它计算给定项目的数量,然后使用该计数.但我想知道是否有一种直接的方式.
当流为空时,这个问题故意忽略了这种情况.
解决方法:
是的,这可以使用自定义收集器实例,该实例将使用具有流中项目计数的匿名对象和重载的toString()方法:
public String format(Stream stream) {
return stream.collect(
() -> new Object() {
StringJoiner stringJoiner = new StringJoiner(",");
int count;
@Override
public String toString() {
return count == 1 ? stringJoiner.toString() : "[" + stringJoiner + "]";
}
},
(container, currentString) -> {
container.stringJoiner.add(currentString);
container.count++;
},
(accumulatingContainer, currentContainer) -> {
accumulatingContainer.stringJoiner.merge(currentContainer.stringJoiner);
accumulatingContainer.count += currentContainer.count;
}
).toString();
}
说明
public interface Collector {
Supplier supplier();
BiConsumer accumulator();
BinaryOperator combiner();
Function finisher();
Set characteristics();
}
我将省略最后一个方法,因为它与此示例无关.
有一个带有以下签名的collect()方法:
R collect(Supplier supplier,
BiConsumer accumulator,
BiConsumer combiner);
在我们的案例中,它将解决:
Object collect(Supplier supplier,
BiConsumer accumulator,
BiConsumer combiner);
>在供应商中,我们使用的是StringJoiner实例(基本上与Collectors.joining()使用的实例相同).
>在累加器中,我们使用StringJoiner :: add()但我们也增加了计数
>在组合器中,我们使用StringJoiner :: merge()并将计数添加到累加器
>在从format()函数返回之前,我们需要调用toString()方法将我们累积的StringJoiner实例包装在[]中(或者保留原样,在单元素流的情况下)
也可以添加一个空案例,我把它留下来,以免使这个收集器更复杂.
标签:java,java-8,java-stream,string
来源: https://codeday.me/bug/20190622/1261748.html