正直これがそれほどのコストを消費する処理だとは思えないのですが
頻繁に使われるという事からか、どのコードチェッカでもなるべく使用を控えるように
する方針になっています。
例えば、数値→文字列の変換は
new Integer(x).toString()
ではなく
Integer.toString()
を使うようにします。
PMD : UnnecessaryConversionTemporary
他にも、Integerにはいくつかのstaticメソッドが用意されているので
知っておいて損は無いでしょう。
Javaの基本クラスには、Integer以外にも
実際には使うことが推奨されていないコンストラクタがいくつか存在します。
例えば、
Boolean b1 = new Boolean(FALSE); Boolean b2 = new Boolean(false);
このような記述は、
Boolean b1 = Boolean.FALSE; Boolean b2 = Boolean.valueOf(false);
とした方がパフォーマンスに優れています。
CheckStyle : IllegalInstantiation
FindBugs : Dm: Method invokes dubious Boolean constructor; use Boolean.valueOf(...) instead
マップ(HashMap等)の全要素にアクセスするとき、
以下のようなコードを書いている人はいないでしょうか。
for (Iterator it = map.keySet(); it.hasNext(); ) {
String key = (String)it.next();
MyBean value = (MyBean)map.get(key);
}
これは、非常に無駄な処理だという事が解るでしょうか。
ループ内で get() を呼び出しています。
これは非常にコストの掛かる処理なのです。keySet() は、マップのキーだけ必要な場合に使用するものです。
今回のように、キーおよび値が必要な場合には代わりに entrySet() を使用します。
for (Iterator it = map.entrySet(); it.hasNext(); ) {
Map.Entry enrty = (Map.Entry)it.next();
String key = (String)entry.getKey();
MyBean value = (MyBean)entry.getValue();
}
keySet() がキーへのイテレータを返すのに対しentrySet() はキーと値へのイテレータを返します。
その為、ループ中に get() を呼び出す必要がありません。
FindBugs : WMI: Inefficient use of keySet iterator instead of entrySet iterator
ちなみに、JDK5ではGenericsおよび拡張ループ構文を使えば以下のように記述できます。
for (Map.Entry<String, MyBean> entry : map.entrySet()) {
String key = entry.getKey();
MyBean value = enrty.getValue();
}
非常にすっきりしています。
ただし、パフォーマンスの面から言えば両者に違いはありません。
このコードには一見キャストが使われていないように見えますが
実は内部でキャストをしています。
Genericsは、コードの見た目をシンプルにしますが
パフォーマンスが上がるわけではないのです。
動的な文字列を扱うこのクラスですが、いくつかの注意点があります。
まず、もし最終的な文字列の長さがわかっているなら
その長さをコンストラクタの引数に渡すべきです。
new StringBuffer(1024);
デフォルトではこのバッファサイズは 16 に初期化され
以後バッファサイズを超える文字列を扱おうとする度に
「バッファを倍に拡張」するという処理が走ります。
例えば、100回のループで毎回10文字ずつappendするという処理をした場合
StringBufferは内部で計6回のバッファ拡張を行っている事になります。
これは(一時的ですが)メモリの無駄使いにもなりますし
何よりバッファ確保のための時間的コストも掛かります。
ちなみに、文字列を + で連結したときには毎回これらの処理が行われるので
それに掛かるコストはこの場合の比ではありません。
PMD : UseStringBufferForStringAppends
FindBugs : SBSC: Method concatenates strings using + in a loop
また、toString() メソッドはStringクラスのインスタンスを生成する為
非常にコストの高い処理となります。
頻繁に呼び出すのは止めましょう。
PMD : UseStringBufferLength