Prática recomendada para o loop for Java

Qual é a melhor maneira de percorrer uma matriz quando você precisa do índice?

Opção 1:

int len = array.length; for (int i = 0; i < len; ++i) { array[i] = foo(i); } 

Opção 2:

 for (int i = 0; i < array.length; i++) { array[i] = foo(i); } 

Ou isso não importa? Ou há uma maneira melhor de fazer isso? Apenas para apontar as diferenças: Em um caso, o comprimento da matriz é avaliado como parte do teste no loop, embora o compilador deva normalmente otimizar isso.


Em segundo lugar, o ++i é diferente aqui do i++ ? Eu definitivamente prefiro ++i se é C ++, mas não tenho certeza para Java.

i++ vs ++i não importa neste caso particular. Embora os mestres de C digam que você armazene array.length em uma variável, os compiladores de otimização modernos tornam isso desnecessário neste caso, desde que o comprimento não mude no loop. Se você está realmente preocupado, pode fazer benchmark de ambos, mas desde que o .length realmente não precisa percorrer todo o array toda vez que você estiver OK.

Geralmente esses dois methods são equivalentes. Você deve notar que em

 for (int i = 0 ; i < foo() ; i++) { ... } 

o foo() é chamado uma vez antes de cada iteração (ao invés de apenas uma vez antes da primeira iteração), então você pode querer levar isso em conta para situações mais complicadas, talvez fazendo algo como

 int n = foo(); for (int i = 0 ; i < n ; i++) { ... } 

que é análogo à sua Opção 1 . Então eu diria que a Opção 1 é certamente a mais segura das duas, mas a maior parte do tempo não deve fazer uma diferença significativa que você use.


Quanto à sua segunda pergunta: ++i primeiro incrementa sua variável e, em seguida, recupera seu valor, i++ primeiro recupera o valor e, em seguida, incrementa. Apenas tente estes dois pedaços de código:

 int i = 0; System.out.println(++i); ------------------------ int i = 0; System.out.println(i++); 

A primeira imprime 1 mas a segunda imprime 0 . É claro que quando ++i e i++ estão sozinhos, não faz diferença.

para se usar “array.length” em loop: Geralmente o compilador fará alguma otimização, como resultado, é equivalente a usar uma variável no loop for

para “i ++” e “++ i” Em C ++, ++ i é preferencial e mais eficiente, mas em Java, eles são equivalentes neste caso.

Além da resposta arshaji, eu queria saber se havia um benefício no desempenho de usar size() em um loop vs armazenar antecipadamente. Acredito que o resultado mostre que o compilador otimiza as coisas e acessar o tamanho de uma lista é o mesmo que acessar uma variável (eu estava preocupado que o fato de ter que passar por uma function diminuísse as coisas).

Aqui está o tempo que leva para os dois diferentes methods de loop:

 for(long i = 0 ; i < mylist.size(); i++){} VS for(long i = 0 ; i < 10_000_000; i++){} 

Aqui está o resultado para uma lista de dez milhões de elems:

 fixed length: ,162,157,151,157,156,159,157,149,150,170,158,153,152,158,151,151,156,156,151,153 getSize: ,164,156,159,154,151,160,162,152,154,152,151,149,168,156,152,150,157,150,156,157 import java.util.ArrayList; import java.util.List; public class Main { final static int LENGTH_SAMPLE = 20; final static long LENGTH = 10_000_000; public static void main(String[] args) { List mylist = new ArrayList<>(); for(long i = 0 ; i < LENGTH; i++){ mylist.add(i); } System.out.println("fixed length:"); for(int i = 0 ; i < LENGTH_SAMPLE; i++){ System.out.printf("," + fixedSize(mylist)); } System.out.println(""); System.out.println("getSize:"); for(int i = 0 ; i < LENGTH_SAMPLE; i++){ System.out.printf("," + fctSize(mylist)); } } private static long fixedSize(List list){ long start = System.currentTimeMillis(); for(long i = 0 ; i < LENGTH; i++){ System.currentTimeMillis(); } return System.currentTimeMillis() - start; } private static long fctSize(List list){ long start = System.currentTimeMillis(); for(long i = 0 ; i < list.size(); i++){ System.currentTimeMillis(); } return System.currentTimeMillis() - start; } }