是的,这可以使用自定义Collector
实例将使用带有流中项目计数和重载的匿名对象toString()
method:
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 https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collector.html接口有以下方法:
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);
- In the
supplier
,我们正在使用一个实例StringJoiner
(基本上是同样的事情Collectors.joining()
正在使用)。
- In the
accumulator
,我们正在使用StringJoiner::add()
但我们也会增加计数
- In the
combiner
,我们正在使用StringJoiner::merge()
并将计数添加到累加器
- 回来之前从
format()
函数,我们需要调用toString()
方法来包装我们积累的StringJoiner
实例在[]
(或者保留原样,如果是单元素流
还可以添加空箱的箱子,我将其省略,以免使该收集器变得更加复杂。