AutoBox/UnBox é a conversão de forma automática entre objetos e tipos primitivos, dicas:

  • Use somente quando houver “descasamento” entre tipos primitivos e objetos empacotadores
  • Não abuse: um Integer não substitui um int (a performance é pior)
  • Cuidado, unboxing com objetos null lança exceção

Probolema:

  • Generics não trabalha com tipos primitivos

Após executar o seguinte teste de performance, constatou-se uma diferênça em média de 25% com uso do autobox. O algoritimo de teste baseou-se em comparar as duas execuções:

  1. faça 1000 vezes
    • varra um ArrayList<Integer>, capturando o valor sem fazer autobox
  2. faça 1000 vezes
    • varra um ArrayList<Integer> usando enhanced-loop fazendo automaticamente unbox para int, capturando o valor e fazendo autbox novamente para um objeto Integer.

Resultado da execução:

___________________________________

autoBoxUnBox()…java.lang.NullPointerException
Sem autoboxing = 6531ms
Com autobox/unbox= 8734ms
Diferença de 26%

___________________________________

Conclusão:

Se sua aplicação é “Performance Driven”, estruturas como o IntHashMap visto no blog anterior entre outras coleções da API que não trabalhem com Generics podem ser a melhor saída para escovar milisegundos de processamento.

Abaixo segue a classe usada no teste:


package update5.boxing;

import java.util.*;

/**
 *
 * @author Fabrício Silva Epaminondas
 */
public class AutoboxingUnboxing {

    static void autoBoxUnBox() {
        // Antes
        int prim = 10;// primitivo
        Integer obj = new Integer(20);// objeto
        Integer nullObj = null;

        // Java 5
        Integer c = 30;// autobox Integer c = new Integer(30)
        prim = obj;// unbox prim = obj.intValue();
        obj = prim;// autobox obj = new Integer(prim);

        try{
            prim = nullObj;// throw NullPointerException
        }catch (NullPointerException e) {
            System.out.println("autoBoxUnBox()..." + e);
        }
    }

    @SuppressWarnings("unchecked")
    static void autoboxComGenerics() {

        // Antes
        Map products = new HashMap();
        products.put(new Integer(2779), new Float(20.45f));
        products.put(Integer.valueOf(922), Float.valueOf(99.99f));
        float price = new Float((Float) products.get(new Integer(922)
                .intValue())).floatValue();

        // AutoBoxing com Generics
        Map<Integer, Float> products2 = new HashMap<Integer, Float>();
        products2.put(10, 20.45f);
        products2.put(20, 99.99f);
        float price2 = products2.get(10);

        // Problema: Performance
        // Generics só aceita Tipos de Objetos e não primitivos

        // Ex: ArrayList de Integers..
        Collection<Integer> values = new ArrayList<Integer>();
        for (int i = 0; i < 100000; i++) {
            values.add(i);
        }

        Integer intObj = null;

        // Teste de Performance 1 (Sem Autobox)
        long time = System.currentTimeMillis();

        // repete 1000 vezes
        for (int i = 0; i < 1000; i++) {
            // for em coleção de objetos Integer
            for (Integer val : values) {
                intObj = val;// sem autobox
            }
        }
        long performance1 = System.currentTimeMillis() - time;
        System.out.println("Sem autoboxing = " + performance1 + "ms");

        // Teste de Performance 2 (Com Autobox/Unbox)
        time = System.currentTimeMillis();

        // repete 1000 vezes
        for (int i = 0; i < 1000; i++) {
            // for em coleção de objetos Integer
            for (int val : values) {// executando unboxing para int
                intObj = val;// autobox para Integer
            }
        }
        long performance2 = System.currentTimeMillis() - time;
        System.out.println("Com autobox/unbox= " + performance2 + "ms");

        System.out.println("Diferença de " + percentGain(performance1,performance2) + "%");
    }

    static long percentGain(long num, long div) {
        return (100 - num*100/div);
    }

    public static void main(String[] args) {

        autoBoxUnBox();

        autoboxComGenerics();
    }
}

Deixe uma resposta