Lendo a documentação Java para a Lista ADT , diz:
A interface List fornece quatro métodos para acesso posicional (indexado) aos elementos da lista. As listas (como matrizes Java) são baseadas em zero. Observe que essas operações podem ser executadas no tempo proporcional ao valor do índice para algumas implementações (a classe LinkedList, por exemplo). Portanto, a iteração sobre os elementos em uma lista é geralmente preferível à indexação através dela, se o chamador não souber a implementação.
O que exatamente isso significa? Eu não entendo a conclusão que é desenhada.
Respostas:
Em uma lista vinculada, cada elemento possui um ponteiro para o próximo elemento:
Para acessar
item3
, você pode ver claramente que precisa percorrer todos os nós da cabeça até chegar ao item3, pois não pode pular diretamente.Assim, se eu quisesse imprimir o valor de cada elemento, se eu escrever isso:
o que acontece é o seguinte:
Isso é terrivelmente ineficiente porque toda vez que você está indexando, ele é reiniciado no início da lista e passa por todos os itens. Isso significa que sua complexidade é efetivamente
O(N^2)
apenas para percorrer a lista!Se, em vez disso, eu fiz isso:
então o que acontece é o seguinte:
tudo em uma única travessia, o que é
O(N)
.Agora, indo para o outro implementação do
List
que éArrayList
, que um é apoiado por uma matriz simples. Nesse caso, as duas travessias acima são equivalentes, uma vez que uma matriz é contígua e permite saltos aleatórios em posições arbitrárias.fonte
REVERSE_THRESHOLD
18java.util.Collections
polegadas, é estranho ver uma resposta tão votada sem a observação.List l = unknownList(); if (l instanceof RandomAccess) /* do indexed loop */ else /* use iterator/foreach */
A resposta está implícita aqui:
Uma lista vinculada não tem um índice inerente; a chamada
.get(x)
exigirá que a implementação da lista encontre a primeira entrada e chame.next()
x-1 vezes (para acesso O (n) ou tempo linear), onde uma lista baseada em matriz pode apenas indexarbackingarray[x]
em O (1) ou tempo constante.Se você olhar para o JavaDoc
LinkedList
, verá o comentárioenquanto que JavaDoc para
ArrayList
tem o correspondenteUma pergunta relacionada intitulada "Resumo do Big-O para Java Collections Framework" possui uma resposta apontando para este recurso, "Java Collections JDK6", que você pode achar útil.
fonte
Embora a resposta aceita esteja certamente correta, posso apontar uma falha menor. Citando Tudor:
Isto não é completamente verdadeiro. A verdade é aquilo
fonte: Designing for Performance, documento Android do Google
Observe que o loop manuscrito se refere à iteração indexada. Eu suspeito que é por causa do iterador que é usado com aprimorada para loops. Produz um desempenho menor na penalidade em uma estrutura que é apoiada por uma matriz contígua. Eu também suspeito que isso possa ser verdade para a classe Vector.
Minha regra é, use o loop for aprimorado sempre que possível e, se você realmente se importa com o desempenho, use a iteração indexada apenas para ArrayLists ou Vectors. Na maioria dos casos, você pode até ignorar isso - o compilador pode estar otimizando isso em segundo plano.
Quero apenas ressaltar que, no contexto do desenvolvimento no Android, ambas as travessias de ArrayLists não são necessariamente equivalentes . Apenas comida para pensar.
fonte
A iteração sobre uma lista com um deslocamento para a pesquisa, como
i
, é análogo ao algoritmo do pintor Shlemiel .Fonte .
Essa pequena história pode facilitar a compreensão do que está acontecendo internamente e por que é tão ineficiente.
fonte
Para encontrar o i-ésimo elemento de uma
LinkedList
implementação, percorre todos os elementos até o i-ésimo.assim
fonte