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:

[sourcecode language=”java”] for(int idx=0;idx<copied.length;idx++) {
copied[idx] = toCopy[idx];
}[/sourcecode]

Para o System.arraycopy:

[sourcecode language=”java”]System.arraycopy(toCopy,0,copied,0,copied.length);[/sourcecode]

E para o Arrays.copyOf:

[sourcecode language=”java”]copied = Arrays.copyOf(toCopy, copied.length);[/sourcecode]

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:

[sourcecode language=”java”]public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);[/sourcecode]

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:

[sourcecode language=”java” highlight=”2″] 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;
}[/sourcecode]

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