どこかから来るさまざまな行の数を数える必要があると想像してください。 多くの場合、次のようなコードが作成されます。
public Map<String, Integer> countStrings() { Map<String, Integer> counts = new HashMap<String, Integer>(); while(true) { String next = getNextString(); if(next == null) break; Integer val = counts.get(next); if(val == null) counts.put(next, 1); else counts.put(next, val+1); } return counts; }
それほど多くの種類の行がなく、十分な繰り返しがある場合、ボクシングは数百万の一時的な整数オブジェクトを作成し、ガベージコレクターはそれをクリーンアップします。 想像するのは怖いです。 いいえ、これは壊滅的なほど遅くはありませんが、それでも手順を2〜3回高速化することは難しくありません。 このために、MutableIntegerを使用します。
このようなクラスはいくつかのライブラリー(たとえばorg.apache.commons.lang )に存在しますが、自分で作成することは難しくありません。 単純な実装は次のようになります。
public class MutableInteger { private int value; public MutableInteger(int value) { this.value = value; } public int intValue() { return value; } public void set(int value) { this.value = value; } public void increment() { value++; } public String toString() { return String.valueOf(value); } }
次に、算術演算の簡単なメソッドを追加できます。 Numberを継承し、Comparableインターフェイスを実装し、equalsとhashCodeを忘れないようにすることも便利です(hashCodeでは、単に値を返すことができます)。 しかし、現在のタスクについては、書かれているもので十分です。 countStrings()は次のように書き換えられるようになりました。
public Map<String, MutableInteger> countStrings() { Map<String, MutableInteger> counts = new HashMap<String, MutableInteger>(); while(true) { String next = getNextString(); if(next == null) break; MutableInteger val = counts.get(next); if(val == null) counts.put(next, new MutableInteger(1)); else val.increment(); } return counts; }
もちろん、Map <String、MutableInteger>を返すことで実装の詳細を公開するのは良くありませんが、java.lang.Numberを継承する場合、Map <String、Number>を返すことができます。 さて、または最後の手段として、数えた後、すべてを新しいマップにコピーします。 同様に、数量だけでなく、オブジェクトのセットに関する他の統計も収集できます。
また、java.util.concurrent.atomic.AtomicIntegerも本質的にMutableIntegerであることに注意してください。ただし、原子性のオーバーヘッドは最初の例のオブジェクトとガベージコレクションの作成コストを超えることもあるため、別個のクラスMutableIntegerが必要です。