我有一个字符串流:
Stream<String> stream = ...;
我想构造一个字符串,将这些项与 ,
连接起来作为分隔符。我这样做如下:
stream.collect(Collectors.joining(","));
现在我想添加一个前缀 [
和后缀 ]
仅当有多个项目时才输出此输出。例如:
-
a
-
[a,b]
-
[a,b,c]
这可以在不首先实现 Stream<String>
的情况下完成吗?到 List<String>
然后查看 List.size() == 1
?在代码中:
public String format(Stream<String> stream) {
List<String> list = stream.collect(Collectors.toList());
if (list.size() == 1) {
return list.get(0);
}
return "[" + list.stream().collect(Collectors.joining(",")) + "]";
}
首先将流转换为列表然后再次转换为流以能够应用 Collectors.joining(",")
感觉很奇怪.我认为循环遍历整个流(在 Collectors.toList()
期间完成)只是为了发现是否存在一个或多个项目是次优的。
我可以实现自己的 Collector<String, String>
它计算给定项目的数量并在之后使用该计数。但我想知道是否有更直接的方法。
这个问题有意忽略了流为空时的情况。
最佳答案
是的,这可以使用自定义 Collector
实例,该实例将使用匿名对象,其中包含流中的项目计数和重载的 toString()
方法:
public String format(Stream<String> 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();
}
说明
Collector
接口(interface)有以下方法:
public interface Collector<T,A,R> {
Supplier<A> supplier();
BiConsumer<A,T> accumulator();
BinaryOperator<A> combiner();
Function<A,R> finisher();
Set<Characteristics> characteristics();
}
我将省略最后一个方法,因为它与此示例无关。
collect()
方法具有以下签名:
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
在我们的例子中,它将解析为:
<Object> Object collect(Supplier<Object> supplier,
BiConsumer<Object, ? super String> accumulator,
BiConsumer<Object, Object> combiner);
- 在
supplier
中,我们正在使用StringJoiner
的实例(基本上与Collectors.joining()
使用的相同)。 - 在
累加器
中,我们使用了StringJoiner::add()
,但我们也增加了计数 - 在
combiner
中,我们使用StringJoiner::merge()
并将计数添加到累加器 - 在从
format()
函数返回之前,我们需要调用toString()
方法将我们累积的StringJoiner
实例包装在中[]
(如果是单元素流,则保持原样
还可以添加一个空箱子的箱子,为了不让这个收集器变得更复杂,我把它省略了。
关于java - 仅当存在多个项目时才向 Collectors.joining() 添加前缀和后缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52672187/