JavaのIntegerCacheについて
java.lang.Integer.valueOf(int)の実装は
public static Integer valueOf(int i) { final int offset = 128; if (i >= -128 && i <= 127) { // must cache return IntegerCache.cache[i + offset]; } return new Integer(i); }
SE5以降上のようになっているので,ここに書いてあるようにboxingしたときに参照比較の結果が変わってくる.
仕様だとintをIntegerにboxingしたときの結果についてはpがint型の時,変換の結果のInteger型rについてはp==r.intValue()をみたすものなら何でもいいので,この結果は実装依存である.
こういうキャッシュすることによって,何が嬉しいかというとインスタンスを生成する手間が省けるのでメモリと実行時間が節約できる.(cf: Flyweight pattern - Wikipedia)
実際に試したところ
import java.util.*; public class Test { static long test(int val){ List<Integer> lst = new LinkedList<Integer>(); long time = System.currentTimeMillis(); for(int i=0;i<100000;i++){ lst.add(val); } time = System.currentTimeMillis() - time; return time; } static long test2(int val){ List<Integer> lst = new LinkedList<Integer>(); long time = System.currentTimeMillis(); for(int i=0;i<100000;i++){ lst.add(new Integer(val)); } time = System.currentTimeMillis() - time; return time; } public static void main(String[] args) { long t100 = 0; long t200 = 0; for(int i=0;i<100;i++){ t100 += test(100); t200 += test(200); } System.out.println("test(100)*100 = " + t100 + "ms"); System.out.println("test(200)*100 = " + t200 + "ms"); t100 = 0; t200 = 0; for(int i=0;i<100;i++){ t100 += test2(100); t200 += test2(200); } System.out.println("test2(100)*100 = " + t100 + "ms"); System.out.println("test2(200)*100 = " + t200 + "ms"); } }
実行結果
test(100)*100 = 5626ms test(200)*100 = 8999ms test2(100)*100 = 9014ms test2(200)*100 = 9064ms
でキャッシュがきいていることがわかる.