Copiar arrays em Java

Em Java, temos algumas maneiras de fazer cópias ou sub-cópias de arrays:

Qual deles é melhor? Criei um código simples de teste que copia 1 milhão de arrays de int com tamanho de 2048. Para a cópia manual foi utilizado o seguinte código:

		for(int idx=0;idx<copied.length;idx++) {
			copied[idx] = toCopy[idx];
		}

Para o System.arraycopy:

System.arraycopy(toCopy,0,copied,0,copied.length);

E para o Arrays.copyOf:

copied = Arrays.copyOf(toCopy, copied.length);

Claro que isso não é um bechmarking muito confiável, mas é só para ter uma noção, logo mais analisaremos a implementação deles. Ao executar os testes na minha máquina a média de execução para as cópias de 1 milhão de arrays na implementação manual foi de 293 millisegundos, para o da classe System, 195 millisegundos e para o da classe Arrays, 1126 millisegundos. Lembrando que não estamos considerando as instanciações dos arrays. Se fizermos isso, o tempo vai ser semelhante para os 3 métodos, já que o tempo de alocação de memória é enormemente maior que o de cópia do array e por esse motivo o Arrays.copyOf demora mais, já que ele faz a instanciação interna conforme veremos posteriormente.

O System.arraycopy utiliza implementação nativa:

public static native void arraycopy(Object src,  int  srcPos,
                                         Object dest, int destPos,
                                         int length);

O código em C++ pode ser visto na source do jdk, por ser nativo e ter diretivas de desempenho específicas para esse método, o método utilizando System.arraycopy tende a ser mais eficiente que o método manual.

Para o Arrays.copyOf temos a seguinte implementação:

    public static int[] copyOf(int[] original, int newLength) {
        int[] copy = new int[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

Como podemos ver na linha 2, ele instancia o array, por isso acaba sendo mais lento que os outros no quesito tempo de execução individual do métodos, mas ele utiliza o System.arraycopy para realizar a cópia.

Meu veridito para uso dos métodos de cópias de array é: nunca utilize o método manual se for cópia simples, utilize o System.arraycopy quando você já tiver o objeto de destino da cópia instanciado ou sua versão do Java é inferior a 1.6 e o Arrays.copyOf em todos os outros casos, pois facilita a leitura e é tão performático quanto o System.arraycopy se você considerar o tempo de instanciação (que é feito internamente).

Sobre: Thiago Galbiatti Vespa

Thiago Galbiatti Vespa é mestre em Ciências da Computação e Matemática Computacional pela USP e bacharel em Ciências da Computação pela UNESP. Coordenador de projetos do JavaNoroeste, membro do JCP (Java Community Process), consultor Oracle, arquiteto de software de empresas de médio e grande porte, palestrante de vários eventos e colaborador de projetos open source. Possui as certificações: Oracle Certified Master, Java EE 5 Enterprise Architect – Step 1, 2 and 3; Oracle WebCenter Portal 11g Certified Implementation Specialist; Oracle Service Oriented Architecture Infrastructure Implementation Certified Expert; Oracle Certified Professional, Java EE 5 Web Services Developer; Oracle Certified Expert, NetBeans Integrated Development Environment 6.1 Programmer; Oracle Certified Professional, Java Programmer; Oracle Certified Associate, Java SE 5/SE 6