Copiando o Conteúdo de um Array em Java

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (2)  (0)

Veja neste artigo uma apresentação e comparação de quatro maneiras distintas para copiar o conteúdo de arrays na linguagem Java.

Introdução

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).

Abordagem 1: 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.

Listagem 1: Copiando o conteúdo de um array para outro com o comando “for”

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]);
		}
		
	} 
}

Abordagem 2: 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.

Listagem 2: Copiando o conteúdo de um array para outro com o método “clone()”

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]);
		}
	}

} 

Abordagem 3: 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.

Listagem 3: Copiando o conteúdo de um array para outro com o método “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]);
		}
	}

} 

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.

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


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]);
	}
}

	
}

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).

Abordagem 4: 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).

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

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]);
		}
	}

} 

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.

Listagem 6: Teste de Desempenho

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));
		
		
	}
	
}
 

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 abordagens (digite e execute diversas vezes o programa Listagem 7 para observaros resultados).

Listagem 7: Teste de Desempenho

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));
		
		
	}
	
}
 

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. Até a próxima.


 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?