maneira mais rápida para iterar uma matriz em Java: variável do laço vs instrução for aprimorada [duplicado]

StackOverflow https://stackoverflow.com/questions/1006395

  •  06-07-2019
  •  | 
  •  

Pergunta

Esta questão já tem uma resposta aqui:

Em Java, é mais rápido para percorrer um array a maneira old-fashioned,

for (int i = 0; i < a.length; i++)
    f(a[i]);

Ou através do formulário mais conciso,

for (Foo foo : a)
    f(foo);

Para uma ArrayList, é a resposta da mesma?

É claro que para a grande maioria do código do aplicativo, a resposta é não faz diferença perceptível assim que mais forma concisa deve ser usado para facilitar a leitura. No entanto, o contexto que eu estou olhando é pesados ??computação técnica, com operações que devem ser executadas bilhões de vezes, por isso mesmo uma pequena diferença de velocidade pode acabar sendo significativo.

Foi útil?

Solução

Se você está em loop através de uma matriz, não deve importar -. A aprimorado para variedade usos de loop acessa de qualquer maneira

Por exemplo, considere o seguinte código:

public static void main(String[] args)
{
    for (String x : args)
    {
        System.out.println(x);
    }
}

Quando compilado com javap -c Test temos (para o método main):

public static void main(java.lang.String[]);
  Code:
   0:   aload_0
   1:   astore_1
   2:   aload_1
   3:   arraylength
   4:   istore_2
   5:   iconst_0
   6:   istore_3
   7:   iload_3
   8:   iload_2
   9:   if_icmpge   31
   12:  aload_1
   13:  iload_3
   14:  aaload
   15:  astore  4
   17:  getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   20:  aload   4
   22:  invokevirtual   #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   25:  iinc    3, 1
   28:  goto    7
   31:  return

Agora, alterá-lo para utilizar um acesso de matriz explícita:

public static void main(String[] args)
{
    for (int i = 0; i < args.length; i++)
    {
        System.out.println(args[i]);
    }
}

Este Decompila para:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   aload_0
   4:   arraylength
   5:   if_icmpge   23
   8:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   11:  aload_0
   12:  iload_1
   13:  aaload
   14:  invokevirtual   #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   17:  iinc    1, 1
   20:  goto    2
   23:  return

Há um código de configuração pouco mais no loop for aprimorado, mas eles estão fazendo basicamente a mesma coisa. Não iterators estão envolvidos. Além disso, eu esperaria-los para obter JITted ao código ainda mais similar.

Sugestão: se você realmente acha que pode fazer uma diferença significativa (que seria apenas nunca fazer se o corpo do laço é absolutamente minúsculo), então você deve referência-lo com sua aplicação real. Essa é a única situação que importa.

Outras dicas

Esta recai na arena da micro-otimização . Ele realmente não importa. Estilisticamente Eu sempre prefiro a segunda porque é mais concisa, a menos que você precisa do contador de loop para outra coisa. E isso é muito mais importantes do que esse tipo de micro-otimização :. Legibilidade

Dito isto, para um ArrayList não haverá muita diferença, mas um LinkedList vai ser muito mais eficiente com o segundo.

medi-la. A resposta em todos os desempenho-pergunta pode depender de VM-versão, processador, memória de velocidade, caches etc Então, você tem que medir-lo para sua plataforma específica.

Pessoalmente eu prefiro a segunda variante, porque a intenção é mais clara. Se o desempenho se torna um problema que pode otimizá-lo mais tarde, de qualquer maneira -. Se esse código é realmente importante para o desempenho de toda a aplicação

Para uma LinkedList:

for(ClassOfElement element : listOfElements) {
  System.out.println(element.getValue());
}

Foi respondida antes:

é existe uma diferença de desempenho entre um loop e uma for-each loop?

Em um array, ou uma coleção RandomAccess você pode obter um pequeno aumento na velocidade fazendo:

List<Object> list = new ArrayList<Object>();

for (int i=0, d=list.size(); i<d; i++) {
    something(list.get(i));
}

Mas eu não me preocuparia em geral. Otimizações como este não vai fazer diferença mais do que 0,1% de seu código. Tente invocar java com -prof para ver onde o código está realmente gastando seu tempo.

Ainda mais rápido é usar o ParallelArray do quadro fork-join (se você tem conjunto de dados grande o suficiente).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top