「繰り返し処理中のオブジェクトの生成は最小限にする」

  • C_CTR009 繰り返し処理中のオブジェクトの生成は最小限にする

繰り返し回数の多いループの内部でオブジェクトを生成することは、生成に時間がかかるため回数によっては、大きなパフォーマンス低下につながることがあります。これを回避するには、ループ外でインスタンス作成しそれを再利用します。
http://74.125.153.132/search?q=cache:nAtQuR5h4GYJ:www.objectclub.jp/community/codingstandard/JavaCodingStandard2004.pdf+java+%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E8%A6%8F%E7%B4%84+%E9%9B%BB%E9%80%9A&cd=1&hl=ja&ct=clnk&gl=jp&lr=lang_ja&client=firefox-a

public class Hoge {
    public static void main(String[] args) {
        int j = 100000000;
        {
            long start = System.currentTimeMillis();
            StringBuffer s = new StringBuffer();
            for (int i = 0; i < j; i++) {
                s.append("hoge");
                s.setLength(0);
            }
            System.out.println("1:"+(System.currentTimeMillis() - start));
        }
        
        {
            long start = System.currentTimeMillis();
            for (int i = 0; i < j; i++) {
                StringBuffer s = new StringBuffer();
                s.append("hoge");
            }
            System.out.println("2:"+(System.currentTimeMillis() - start));
        }
    }
}
1:11786
2:7800

new StringBuffer()ではインスタンス変数valueにchar配列を定義するだけだが、setLength(int newLength)では引数チェック、バッファとの大小チェック、文字との大小チェックを経て、ようやく長さが0になる。たぶんこの違い。
StringBufferのバッファ初期値は16で、16文字を超えるとバッファを2倍に拡張するしつつ値をコピーするので、appendする文字が20文字とかだったら、もしかして後者の方が早いかもしれない。使い回すオブジェクトのバッファは、既に拡張されているので。ただ、その見込みがあるのであれば、new時に容量を指定する方を選ぶべきだったり。

(追記:それでも、文字が多いと前者の方が少し早い様子。んー、この差ってどこからくるんだろか。)
(さらに:いや、バッファの初期値が実際にappendされる数に近ければ、後者の方が早い。"hoge"を25個appendするなら、バッファ初期値は100など。ま、あれだ。clearメソッドがないオブジェクトを使い回すなってことかw)

パフォーマンスに関する意見は短命なものです。パフォーマンスに関する助言に出くわしたときは、それを事実として受け入れる前に、それが時代遅れではないかという疑問を持ってください。

(...)まず最初に、変更によって本当にアプリケーションのパフォーマンスが向上するのか、そして、そもそもそのアプリケーションにパフォーマンスの改善が必要なのか自問自答してください。
Javaの理論と実践: パフォーマンスの都市伝説

もっともこの問題は、時代的なものはあんまり関係なさそうだけどね。