読者です 読者をやめる 読者になる 読者になる

感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

文字列の連結にStringBufferクラスを使うワケ(内部仕様編)

<スポンサーリンク>

2003年に出版された化石のような本にいいことが書いてあったのでメモ。

文字列の連結にStringBufferクラスを使うワケ

StringとStrigBufferでパフォーマンスに違いが出ることは、以前の記事にも書いたけれど、内部でどのように処理をしているのかはちゃんと理解していなかった。
こんな感じでStringで文字列を連結させるとき、何をしているか?

String hoge = "hoge";
String fuga = "fuga";
String hogefuga = hoge + fuga;

大前提はStringクラスは不変だということ。
じゃあ、どうやって連結してる?というと、コンパイラによって、以下のようにコンパイルされる。

String hogefuga = (new StringBuffer()).append(hoge).append(fuga),toString();

こうやると、
1.StringBufferクラスの生成
2.Stringクラスの生成(StringBuffer#toStringによって生成される)
3.Stringクラス、StringBufferクラスが内部で保持しているchar型配列の生成
という処理を内部でやってしてしまう。

これがStringBufferとなんで差が出てしまうかというと、StringBufferクラスは内部でバッファを用意していて、バッファが一杯になったときのみ、StringBufferクラスが内部で保持しているchar配列の生成という処理を行う。
配列の拡張は、「アルゴリズムとデータ構造」のリストの勉強すると痛感するんだけど、けっこう重い処理になってしまう。

また、Stringクラスで+演算子によって文字列を連結する場合は、オブジェクトの生成と破棄が非常に多く発生するため、ガーベジコレクタが頻繁に動作することになる。

上記でStringBufferの「バッファ」について触れたが、あらかじめ必要な文字列のサイズがわかるときは、以下のようにStringBuffer生成時にあらかじめ十分な量を確保することが大事である。

StringBuffer sb = new StringBuffer(2000);

そうすると、新たに配列を生成するコストが最小限に押さえられる。

いいことが書いてあった本

J2EEパフォーマンスチューニング徹底解説―見えないところを手抜きしないWebシステム実現のために (アドバンストサーバサイドプログラミング)

J2EEパフォーマンスチューニング徹底解説―見えないところを手抜きしないWebシステム実現のために (アドバンストサーバサイドプログラミング)


ずいぶん古いけど、古きを温ねて新しきを知るというやつですね。