最近、Java 8 class StringJoiner
に遭遇しました。バックエンドで StringBuilder
を使用し、文字列を追加する非常に簡単な操作も実行するため、このクラスの必要性を理解してください。
このクラスの本当の目的を実際に理解していないことで何かが欠けていますか?
StringJoiner
は、Stream
で文字列を結合する必要がある場合に非常に便利です。
例として、文字列のリストに従う必要がある場合:
final List<String> strings = Arrays.asList("Foo", "Bar", "Baz");
使用する方がはるかに簡単です
final String collectJoin = strings.stream().collect(Collectors.joining(", "));
StringBuilder
の場合:
final String collectBuilder =
strings.stream().collect(Collector.of(StringBuilder::new,
(stringBuilder, str) -> stringBuilder.append(str).append(", "),
StringBuilder::append,
StringBuilder::toString));
StringJoiner Javadoc の例は、これをカバーするのに非常に優れています。エントリを追加する行為からセパレーターの選択を抽象化することの要点です。例えばジョイナーを作成し、使用するセパレーターを指定してライブラリに渡し、要素の追加を行うか、その逆を行うことができます。
文字列「[George:Sally:Fred]」は次のように構築できます。
StringJoiner sj = new StringJoiner(":", "[", "]"); sj.add("George").add("Sally").add("Fred"); String desiredString = sj.toString();
StringJoinerを使用して、Collectors.joining(CharSequence)を使用してStreamからフォーマットされた出力を作成できます。例えば:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4); String commaSeparatedNumbers = numbers.stream() .map(i -> i.toString()) .collect(Collectors.joining(", "));
いくつかのユースケースでコードを簡素化する場合があります。
List<String> list = // ...;
// with StringBuilder
StringBuilder builder = new StringBuilder();
builder.append("[");
if (!list.isEmpty()) {
builder.append(list.get(0));
for (int i = 1, n = list.size(); i < n; i++) {
builder.append(",").append(list.get(i));
}
}
builder.append("]");
// with StringJoiner
StringJoiner joiner = new StringJoiner(",", "[", "]");
for (String element : list) {
joiner.add(element);
}
StringJoiner
は一種のCollectorですが、Collector
インターフェイスを実装していません。それだけで動作します。区切り文字、接頭辞、接尾辞を渡すことができるほか、StringJoiner
を使用して、Collectors.joining(CharSequence)
を呼び出してStream
からフォーマットされた出力を作成できます。
これは、パラレルストリームで作業する場合に特に便利です。これは、ある時点で、並行して処理されているバッチがjoinedStringJoiner
が発生する場所です。
StringJoinerは、StringBuilderを使用するよりもはるかに簡単です。非常にシンプルなコードは
StringJoiner sj = new StringJoiner(",");
sj.add("aaa");
sj.add("bbb");
sj.add("ccc");
String result = sj.toString(); //aaa,bbb,ccc