ジョン・ドウ:
私は、文字列のストリームを持っています:
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()
)は、1つ以上の項目を(s)が存在する場合にのみ発見するが。
私は自分自身を実装することができCollector<String, String>
、その後カウント与えられた項目や使用回数をカウントします。directerの方法がある場合しかし、私は疑問に思って。
ストリームが空の場合、この質問は、意図的にそこにケースを無視します。
シンタグマ:
はい、これはカスタム使用可能である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
インタフェースは次のメソッドがあります。
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()
使っているが)。 - では
accumulator
、私たちが使用しているStringJoiner::add()
が、我々はうまくとしてカウントをインクリメント - では
combiner
、私たちが使用しているStringJoiner::merge()
とアキュムレータに数を追加 - 戻る前に
format()
機能、我々は呼び出す必要がありtoString()
、当社の蓄積ラップする方法をStringJoiner
でインスタンスを[]
単一要素ストリームの場合には、(またはされているとして、それを残します
空の場合の場合も、私はこのコレクタはより複雑にしないためにそれを残し、追加することができます。