本当にそこまで気にしなければいけないのかを計測してみました。
・計測内容
JDK5とJDK6で下記処理を50万回行った際の処理時間を計測。
- List#newとList#clear
- StringBuffer#newとStringBuffer#setLength
- StringBuilde#newとStringBuilder#setLength
・計測結果
計測内容 | JDK5 | JDK6 |
List:new | 3,422ms | 3,032ms |
List:clear | 3,391ms | 2,906ms |
StringBuffer:new | 4,375ms | 3,750ms |
StringBuffer:setLength | 3,687ms | 3,297ms |
StringBuilder:new | 4,000ms | 3,421ms |
StringBuilder:setLength | 3,750ms | 3,141ms |
・結果
やはり、インスタンスを生成しなおすよりはArrayList#clearやStringBuffer#setLengthを使ったほうが早いことが分かりますね。また、JDK6では処理の最適化が行われているのか全体的に性能は改善しています。ただし、インスタンス生成をした場合としなかった場合の、性能差はあまり変わっていません。
・どう対応すべきか
計測結果を見ると、明らかにインスタンス生成のコストがオーバヘッドになっていることが分かります。ただし、だからといって何が何でもインスタンス生成を控えるべきかといったら??な気がします。実システムでは可読性や保守性も意識して作成しなければならないため、インスタンス生成のコストを削減することによって、それらを犠牲にすることはNGであるはずです。たとえば、参照渡しを多用していて値の書き変わる場所やタイミングが不明瞭になったり、クラス間の結合度が高くなったりするのはよろしくないですよね。
ただし、限られたスコープ内で閉じられている のであれば、積極的にコスト削減を行っていくべきですよ。
まぁ、インスタンス作成のコスト削減と可読性・保守性のトレードオフを見極めて適宜判断していくしかないのかなっと。