Em diversas situações práticas, quando trabalhamos com arrays torna-se necessário realizar uma cópia de seu conteúdo para realizar algum tipo de processamento. A linguagem Java oferece diferentes formas para copiar o conteúdo de um array para outro:

  • Implementando um laço com o comando for.
  • Utilizando o método clone.
  • Utilizando System.arraycopy.
  • Utilizando Arrays.copyOf.

Este artigo tem por objetivo apresentar exemplos de utilização destas quatro abordagens e também realizar uma breve discussão a respeito das vantagens e desvantagens de cada uma. Nos exemplos apresentados, a é o vetor origem (vetor os dados originais) e b o vetor destino (que receberá os dados copiados).

Comando “for”

É a maneira mais tradicional de realizar a operação, podendo ser utilizada em qualquer linguagem de programação. Nesta abordagem precisamos inicialmente reservar espaço para o vetor destino (vetor b). Depois disso, implementa-se um laço for que varre todo o conteúdo do vetor origem (vetor a), copiando o valor armazenado em cada posição (um por um) para a posição correspondente em b. Esta implementação é mostrada na Listagem 1.


import java.util.Random;

public class CopiaFor {

	public static void main(String[] args) {
		
		//(1) cria o array "a" e o preenche com uma sequência de números 
		aleatórios
		int [] a = new int[5];
		Random numeros = new Random();
		for (int i=0; i < a.length; i++) {
			a[i]=numeros.nextInt();
			System.out.println("a[" + i + "]=" + a[i]);
		}
		System.out.println();
		
		//(2) Copia o conteúdo de "a" para "b" com o uso de laço for
		
		int [] b = new int[a.length];                //primeiro é preciso 
		reservar espaço para b
		for (int i=0; i < a.length; i++) b[i]=a[i];  //agora podemos copiar
		
		//(3) exibe o conteúdo de "b" 
		for (int i=0; i < a.length; i++) {
			System.out.println("b[" + i + "]=" + b[i]);
		}
		
	} 
}
Listagem 1. Copiando o conteúdo de um array para outro com o comando for

Método “clone()”

Na linguagem Java, o método clone() é utilizado para clonar um objeto, ou seja, para gerar uma cópia de seu conteúdo. O método pode ser utilizado para duplicar o conteúdo de um array, conforme mostra a Listagem 2. Observe que nesta abordagem não é preciso reservar espaço para o vetor “b”, pois o método clone() faz isso automaticamente. Além, disso basta uma simples linha de código sem o uso de qualquer parâmetro para realizar a operação.


import java.util.Random;


public class CopiaClone {

public static void main(String[] args) {
		
		//(1) cria o array "a" e o preenche com uma sequência de números aleatórios
		int [] a = new int[5];
		Random numeros = new Random();
		for (int i=0; i < a.length; i++) {
			a[i]=numeros.nextInt();
			System.out.println("a[" + i + "]=" + a[i]);
		}
		System.out.println();
		
		//(2) Copia o conteúdo de "a" para "b" com o uso do método “clone()”
		
		int [] b = a.clone();  //este comando reserva espaço para "b" 
//e faz a cópia do conteúdo de "a" para "b"
		
		//(3) exibe o conteúdo de "b" 
		for (int i=0; i < a.length; i++) {
			System.out.println("b[" + i + "]=" + b[i]);
		}
	}

} 
Listagem 2. Copiando o conteúdo de um array para outro com o método clone()

Método “System.arraycopy”

Outra forma de copiar arrays é com o uso da classe System. Ela possui um método denominado arraycopy que oferece uma forma eficiente de realizar a operação. Para utilizar o método é preciso especificar alguns parâmetros, conforme indicado em sua assinatura:


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

Os argumentos src e dest representam os vetores origem e destino, respectivamente (em nosso exemplo, esses vetores chamam-se a e b). O argumento srcPos é a posição inicial no array origem. O argumento destPos é a posição inicial no array destino. Por fim, length é utilizado para especificarmos o número de elementos que serão copiados.

O programa da Listagem 3 mostra como realizar a cópia do conteúdo de a para b com o uso de System.arraycopy.


import java.util.Random;


public class CopiaArrayCopy {
	
public static void main(String[] args) {
		
		//(1) cria o array "a" e o preenche com uma sequência de números aleatórios
		int [] a = new int[5];
		Random numeros = new Random();
		for (int i=0; i < a.length; i++) {
			a[i]=numeros.nextInt();
			System.out.println("a[" + i + "]=" + a[i]);
		}
		System.out.println();
		
		//(2) Copia o conteúdo de "a" para "b" com o uso do método “System.arraycopy”
		
		int [] b = new int[a.length];                //primeiro é preciso reservar espaço para b
		System.arraycopy(a, 0, b, 0, a.length);  //agora podemos copiar
		
		
		//(3) exibe o conteúdo de "b" 
		for (int i=0; i < a.length; i++) {
			System.out.println("b[" + i + "]=" + b[i]);
		}
	}

} 
Listagem 3. Copiando o conteúdo de um array para outro com o método System.arraycopy

Para usar o método System.arraycopy é preciso primeiro reservar espaço para b. Depois podemos chamar o método, especificando os parâmetros de forma adequada. Em nosso exemplo a chamada ao método foi feita da seguinte forma:


System.arraycopy(a, 0, b, 0, a.length);

Com isto, estamos dizendo que desejamos copiar o conteúdo de a a partir de sua posição 0 para b também a partir de sua posição 0. O número de elementos a ser copiado é igual a a.length, ou seja, desejamos copiar todos os elementos armazenados em a.

O método System.arraycopy parece mais difícil de utilizar do que os anteriormente apresentados, pois ele requer a utilização de parâmetros. Porém o seu uso é vantajoso em determinadas situações. Para começar, uma grande vantagem é que o método é mais flexível, pois oferece a possibilidade de copiar apenas parte dos dados que estão armazenados em “a” para “b”. Este recurso é exemplificado no programa da Listagem 4.


public class CopiaParte {

public static void main(String[] args) {
	
	//(1) cria o array "a" e o preenche com os caracteres da palavra "utopia"
	char[] a = { 'u', 't', 'o', 'p', 'i', 'a'};
			

	//(2) Copia apenas a palavra "top" para o array b, usando “System.arraycopy()”
	
	char [] b = new char[3];          //primeiro é preciso reservar espaço para b
	System.arraycopy(a, 1, b, 0, 3);  //agora copiamos a palavra "top"
	
	
	//(3) exibe o conteúdo de "b" 
	for (int i=0; i < b.length; i++) {
		System.out.println("b[" + i + "]=" + b[i]);
	}
}

	
}
Listagem 4. Copiando parte do conteúdo de um array com o método System.arraycopy

No exemplo, copiamos apenas os valores armazenados nas posições 1, 2 e 3 de a para b (veja a ilustração na Figura 1).

Copiando parte do conteúdo de um array com o método System.arraycopy
Figura 1. Copiando parte do conteúdo de um array com o método System.arraycopy

Outra vantagem do método System.arraycopy encontra-se no fato de ele ser mais eficiente em situações onde precisamos fazer muitas operações de cópia e o vetor destino é sempre o mesmo (mostraremos um exemplo no final deste artigo).

Método “Arrays.copyOf”

Por fim, apresentamos a cópia com o uso do método Arrays.copyOf. Nesta abordagem, o conteúdo total ou parcial do array é automaticamente duplicado em memória, como mostra o programa da Listagem 5. Veja que é preciso importar a classe Arrays (import java.util.Arrays).


import java.util.Arrays;
import java.util.Random;


public class CopiaCopyOf {
	
public static void main(String[] args) {
		
		//(1) cria o array "a" e o preenche com uma sequência de números aleatórios
		int [] a = new int[5];
		Random numeros = new Random();
		for (int i=0; i < a.length; i++) {
			a[i]=numeros.nextInt();
			System.out.println("a[" + i + "]=" + a[i]);
		}
		System.out.println();
		
		//(2) Copia o conteúdo de "a" para "b" com o uso do método “Arrays.copyOf()”

		int [] b = Arrays.copyOf(a, a.length);  //automaticamente reserva espaço para "b" 
//e copia o conteúdo de "a" para "b"
		
		
		//(3) exibe o conteúdo de "b" 
		for (int i=0; i < a.length; i++) {
			System.out.println("b[" + i + "]=" + b[i]);
		}
	}

} 
Listagem 5. Copiando o conteúdo de um array para outro com o método Arrays.copyOf

O método oferece duplicar automaticamente o conteúdo de “a” em memória. Além disso, é possível especificar o número de elementos a ser copiado no segundo parâmetro. Porém, o método é menos flexível do que System.arraycopy. Utilizando Arrays.copyOf, podemos copiar os n primeiros elementos de “a” (por exemplo: os três primeiros), mas não é possível especificar uma posição no meio do array origem (por exemplo: copiar do segundo ao quinto elemento de a).

Teste de Desempenho

Nesta seção apresentamos um teste para avaliar o desempenho dos quatro métodos apresentados em uma situação onde serão realizadas algumas centenas de milhares de operações de cópia e o vetor “b” já encontra-se instanciado de antemão. O código é apresentado na Listagem 6.


import java.util.Arrays;
import java.util.Random;


public class AvaliacaoCopiaArrays {

	public static void main(String[] args) {
		
		//(0) declara de variáveis e preenche o array "a"
		long startTime;
		long endTime;
		
		int [] a = new int[9999999];
		int [] b = new int[a.length];
		
		Random numeros = new Random();
		for (int i=0; i < a.length; i++) a[i] = numeros.nextInt();
		
		//=----------------------------------------
		//- cópia com a abordagem 1 (comando for)
		//=----------------------------------------
		startTime = System.currentTimeMillis();
		
		for (int i=0; i < a.length; i++) b[i] = a[i];
		
		endTime = System.currentTimeMillis();

		System.out.println("Metodo 1 -> tempo de processamento -> " + (endTime - startTime));

		//=----------------------------------------
		//- cópia com a abordagem 2 (método clone)
		//=----------------------------------------
		startTime = System.currentTimeMillis();
		
		b = a.clone();
		
		endTime = System.currentTimeMillis();

		System.out.println("Metodo 2 -> tempo de processamento -> " + (endTime - startTime));

		//=----------------------------------------
		//- cópia com a abordagem 3 (método System.arraycopy)
		//=----------------------------------------
		startTime = System.currentTimeMillis();
		
		System.arraycopy(a, 0, b, 0, a.length);
		
		endTime = System.currentTimeMillis();

		System.out.println("Metodo 3 -> tempo de processamento -> " + (endTime - startTime));

		//=----------------------------------------
		//- cópia com a abordagem 4 (método Arrays.copyOf)
		//=----------------------------------------
		startTime = System.currentTimeMillis();
		
		b = Arrays.copyOf(a, a.length);
		
		endTime = System.currentTimeMillis();

		System.out.println("Metodo 4 -> tempo de processamento -> " + (endTime - startTime));
		
		
	}
	
}
Listagem 6. Teste de Desempenho

Um possível resultado da execução do programa é apresentado na Figura 2.

Resultado da Execução do Programa da Listagem 6
Figura 2. Resultado da Execução do Programa da Listagem 6

Observe que os métodos 1 (comando for) e 3 (System.arraycopy) obtiveram melhor desempenho. Por que? Na verdade isso só aconteceu porque estas abordagens não reservam espaço em memória para o vetor destino (ou seja, elas exigem que este espaço já tenha sido alocado, o que foi feito logo no início do nosso programa). Desta forma, elas não gastam tempo com essa operação. Sendo assim, elas são indicadas no caso em que precisaremos copiar muitos vetores para um mesmo vetor temporário, pois nesse caso basta reservar espaço uma vez para o vetor temporário e usá-lo sempre que for preciso copiar qualquer array.

Para qualquer outra situação, não faz muita diferença utilizar qualquer um dos métodos. Se modificarmos o nosso programa de avaliação, realizando a alocação do espaço para o vetor destino em conjunto com as abordagens 1 e 3, o tempo de execução não será tão diferente para cada uma das abordagens (digite e execute diversas vezes o programa Listagem 7 para observar os resultados).


import java.util.Arrays;
import java.util.Random;


public class AvaliacaoCopiaArrays {

	public static void main(String[] args) {
		
		//(0) declara de variáveis e preenche o array "a"
		long startTime;
		long endTime;
		
		int [] a = new int[9999999];
		
		Random numeros = new Random();
		for (int i=0; i < a.length; i++) a[i] = numeros.nextInt();
		
		//=----------------------------------------
		//- cópia com a abordagem 1 (comando for)
		//=----------------------------------------
		startTime = System.currentTimeMillis();
		
		int [] b1 = new int[a.length]; //aloca espaço para b1
		for (int i=0; i < a.length; i++) b1[i] = a[i];
		
		endTime = System.currentTimeMillis();

		System.out.println("Metodo 1 -> tempo de processamento -> " 
		+ (endTime - startTime));

		//=----------------------------------------
		//- cópia com a abordagem 2 (método clone)
		//=----------------------------------------
		startTime = System.currentTimeMillis();
		
		int[] b2 = a.clone();
		
		endTime = System.currentTimeMillis();

		System.out.println("Metodo 2 -> tempo de processamento -> " 
		+ (endTime - startTime));

		//=----------------------------------------
		//- cópia com a abordagem 3 (método System.arraycopy)
		//=----------------------------------------
		startTime = System.currentTimeMillis();
		 
		int [] b3 = new int[a.length]; //aloca espaço para b
		System.arraycopy(a, 0, b3, 0, a.length);
		
		endTime = System.currentTimeMillis();

		System.out.println("Metodo 3 -> tempo de processamento -> " 
		+ (endTime - startTime));

		//=----------------------------------------
		//- cópia com a abordagem 4 (método Arrays.copyOf)
		//=----------------------------------------
		startTime = System.currentTimeMillis();
		
		int [] b4 = Arrays.copyOf(a, a.length);
		
		endTime = System.currentTimeMillis();

		System.out.println("Metodo 4 -> tempo de processamento -> " 
		+ (endTime - startTime));
		
		
	}
	
}
Listagem 7. Teste de Desempenho

Cada abordagem possui as suas características, que resumiremos a seguir:

  • A sintaxe do método clone() é mais econômica e ele faz a duplicação do conteúdo do vetor origem automaticamente (não há necessidade de reservar espaço para o vetor destino) e não requer nenhum parâmetro. Porém se queremos copiar apenas parte do vetor origem não vale a pena – é melhor usar System.arraycopy. Se precisamos realizar diversas cópias para um vetor temporário instanciado uma única vez, também não vale a pena usar o método clone().
  • O método System.arraycopy é o mais flexível de todos, pois permite copiar qualquer seção do array origem para o array destino. Além disso, é o método mais eficiente na situação em que precisamos realizar diversas cópias para um vetor temporário instanciado uma única vez. A desvantagem do método é que ele necessita de muitos parâmetros.
  • O método Arrays.copyOf funciona de maneira similar ao método clone, oferecendo apenas o recurso de possibilitar a cópia dos n primeiros elementos do vetor origem.
  • A abordagem que faz a cópia usando o comando for é mais tradicional e tão eficiente quanto qualquer outra.

Assim encerramos o artigo sobre a operação de duplicação de conteúdo de arrays em Java.