せてぃーずノート

Javaのイベント参加レポートとかを書いたりします。

Java8時代の文字列結合のまとめが気になったので試してみた

元ネタはこちら

Java8時代の文字列連結まとめ - きしだのはてな

だいぶ今更感がありますけど、気になったことが合ったので試してみました。

  • 気になったこと1
    データ量が多くなったら急に性能が落ちるケースってあるのか?

  • 気になったこと2
    一応SIer所属なので、「漢は黙ってStringBuffer」も比較対象に加えたい。

というわけで、きしださんの作ったソースのコピペ をベースに、StringBufferで結合する素敵メソッドを追加。
それに対して文字列リストの要素数を1倍、10倍、100倍のケースで測ってみました。

まずはオリジナルの要素数で。

stringJoin:1812ms
stringBuilderJoinMem:958ms
stringArrayJoining:686ms
charBufferJoin:773ms
stringBufferJoin:1240ms

これはきしださんの結果と大体一致しています。
String#joinを使われるよりは、StringBufferの方がマシというところでしょうか。

次に文字列の要素数を10倍にして実行。
予想ではだいたい10倍位の時間になるはずですが。。。

stringJoin:18484ms
stringBuilderJoinMem:10775ms
stringArrayJoining:8595ms
charBufferJoin:13221ms
stringBufferJoin:12630ms

アイエエエ!?CharBufferナンデ!?
素数が10倍になったら処理時間が20倍くらいになってます。
まさかのStringBufferよりも遅いという結末。

思い当たるフシとして、allocateのサイズが割りと適当なこと。
そこで、allocateの引数を90000(適当な数値)結合した文字列の長さに合わせた79995バイトに変更してみました。

CharBuffer buffer = CharBuffer.allocate(79995);

再測定した結果はこんな感じです。

stringJoin:18971ms
stringBuilderJoinMem:10594ms
stringArrayJoining:8212ms
charBufferJoin:12023ms
stringBufferJoin:12849ms

StringBufferより辛うじて早いけれど・・・という感じです。
ちなみにその後に行った100倍の結果はこちら。

stringJoin:197357ms
stringBuilderJoinMem:111888ms
stringArrayJoining:89730ms
charBufferJoin:129791ms
stringBufferJoin:132432ms

こちらは比較的予想通りの結果です。
CharBufferも前回のリミット見直しのおかげでStringBufferより早いです。

まとめ

試してみたなりのまとめです。

  • カツカツな性能が求められていない限り、StringBuilderが安定。
  • CharBufferのリミットはしっかり設定しよう。
    本来は文字列結合だけの目的で使うクラスじゃないのでしょうが・・・。
  • あれ、Java8の要素があまりないよ?

ま、まぁ、+演算子で結合というような事をしない限りは、文字列結合の速度で問題にはならない気がします。

補足

ByteBufferは使うけど、CharBuffer使ったの初めてかも・・・。