Dica de Performance: Estruturas de repetição percorrendo Vetores, Array, ArrayList, List e etc

Pessoal bom dia,

Abaixo mostrarei uma dica de performance de como percorrer um vetor através da estrutura de repetição FOR:

A maioria dos programadores fazem assim:

String[] array = new String[1000000];
		
for(int i=0; i<array.length; i++){
	System.out.println(array[i]);
}

Ou seja, utilizam o método lenght() para pegar o tamanho do vetor e percorre-lo. Isso está certo, não está errado essa maneira acima.
Abaixo segue o mesmo código com uma pequena alteração, vejam:

String[] array = new String[1000000];
int j = array.length;
				
for(int i=0; i<j; i++){
	System.out.println(array[i]);
}

Eu coloco o tamanho do vetor na variável j do tipo int, e esta servirá de base para FOR percorrer até o final do vetor.
Porque fiz isso? Digitei mais comandos, ao invés do código ficar mais enxuto, criei mais uma linha.

Então respondendo a essa pergunta:

O que acontece, toda vez que percorro FOR, faço uma chamada ao método length(), que me retorna um número inteiro com o tamanho do vetor, isso consume processamento da maquina, se eu tiver um array de 1000000 objetos, então ele fará 1000000 chamadas ao método length e retornará sempre o mesmo valor do tamanho do array. Não acham um pouco de perda de processamento? Não acham uma coisa meio redundante? Chamar toda vez o mesmo método, para retorna o mesmo valor?

Imagine que toda vez que você for ao banheiro, você ter que ir avisar seu chefe - “Chefe to indo ao banheiro, já volto!” - se você tiver muito apertado e quiser ir com pressa ao banheiro…

Então como meu objetivo neste caso é obter PROCESSAMENTO, então utilizo uma variável em MEMÓRIA com o tamanho do array. As 1000000 interações do FOR consultará a variável que está em memória e não fará uma chamada de método.

É o mesmo que dizer: “Chefe toda vez que quiser ir no banheiro, é só abrir a porta e ir? Ele responde, sim, é só abrir a porta!!”
Nem sempre escrever mais linhas de código significa processamento lento!

Obs: Isso é uma dica para quem está começando a programar e entrando no mundo JAVA. Talvez para Seniors seja óbvio, para quem nunca trabalhou na área e está na faculdade, é novidade.

Permita-me discordar.

  1. O Just-In-Time Compiler percebe que você quer percorrer o array se você usar array.length. Nesse caso, onde você tem uma restrição constante (já que um array não varia de compirimento durante sua execução), ele pode até remover o teste de limites do índice do array. Portanto,
 for(int i=0; i<array.length; i++){  
     System.out.println(array[i]);  
 }

pode até ser mais rápido que o código dado. Note que é “array.length” (uma propriedade, de valor constante), não “String.length()” (que seria uma chamada de função, que o compilador não pode otimizar e por conseguinte será sempre chamada a cada iteração do loop.

Se você quer percorrer uma string, o correto é usar a técnica citada pelo rsantik. Usualmente você faria algo como:

String s = "................".
for (int i = 0, n = s.length(); i < n; ++i) {
    char ch = s.charAt(i);
}

Note o truque usado, que é o de declarar 2 variáveis no mesmo for, sendo que a primeira declaração é o do contador e a segunda é o do limite da iteração. Dessa forma você também limita o escopo da variável “n”, para que ela não “vaze” para fora do loop, onde provavelmente você não iria usá-la.

1 curtida

Ao percorrer um List, use um Iterator se esse List for um LinkedList, e um índice simples se for um ArrayList.

É pena que não existe uma interface (talvez chamada RandomAccess) indicando que é mais rápido usar um índice simples que um Iterator. Senão você poderia usar algo como:

List<T> list = __________;
if (list instanceof RandomAccess) {
    for (int i = 0, n = list.size(); i < n; ++i) {
        T t = list.get(i);
        ____
    }
} else {
    for (Iterator<T> it = list.iterator(); it.hasNext(); ) {
        T t = it.next();
        ____
    }
}

Perfeito entanglement.

Segue um link abaixo para ajudar sobre o assunto