Box / Unboxing vs. Encapsulamento: Java’s `Map `

Problema: quero um mapa que armazene um número inteiro como seu valor. Agora
tenho duas abordagens:

  1. Use qualquer coisa como chave e Integer(inteiro não primitivo) como valor, ou
  2. Use qualquer coisa como chave e uma classe que contenha int(inteiro primitivo) como valor.

Qual devo usar? A primeira solução parece muito legal, nada
a fazer. Apenas instale o novo Integere pronto. Por outro lado, em termos de
desempenho, ele fará boxing / unboxing desnecessário se
não for manuseado corretamente. Lembre-se de que só podemos usar
inteiros primitivos para fazer cálculos e inteiros primitivos para armazenar valor
no mapa.

O teste

Benchmark withBoxing = new Benchmark() {
public void run() {
Map<String, Integer> a = new HashMap<String, Integer>();

// Simulate much boxing
for (int i = 0; i < MAX; i++) {
a
.put("" + i, i);
}

// Simulate much unboxing
for (int i = 0; i < MAX; i++) {
// A hack so that JVM does not optimize this code.
hack
+= a.get("" + i);
hack
= hack % 1000;
}
}
};
Benchmark encapsulate = new Benchmark() {
public void run() {
Map<String, EncapsulatedInteger> a = new HashMap<String, EncapsulatedInteger>();

// No boxing/unboxing, but new class
for (int i = 0; i < MAX; i++) {
a
.put("" + i, new EncapsulatedInteger(i));
}

for (int i = 0; i < MAX; i++) {
// A hack so that JVM does not optimize this code.
hack
+= a.get("" + i).v;
hack
= hack % 1000;
}
}
};

O comando de execução

javac MapPerf.java; java -Xmx1024m -cp . MapPerf

O resultado

$ javac MapPerf.java; java -Xmx1024m -cp . MapPerf
Boxing/unboxing: 10973 ms
Encapsulation: 7036 ms

Resumo

Com um Integervalor, a rotina é 50% mais lenta por causa de
boxing / unboxing desnecessário

Github

https://github.com/mufid/boxing-unboxing-java-perf