Resumo ArrayList
com ArrayDeque
é preferível em muitos mais casos de uso do que LinkedList
. Se você não tiver certeza, basta começar ArrayList
.
LinkedList
e ArrayList
são duas implementações diferentes da interface da lista. LinkedList
implementa-o com uma lista duplamente vinculada. ArrayList
implementa-o com uma matriz de redimensionamento dinâmico.
Como nas operações de lista e matriz vinculadas padrão, os vários métodos terão tempos de execução algorítmicos diferentes.
Para LinkedList<E>
get(int index)
é O (n) (com n / 4 etapas em média), mas O (1) quando index = 0
ou index = list.size() - 1
(nesse caso, você também pode usar getFirst()
e getLast()
). Um dos principais benefícios de LinkedList<E>
add(int index, E element)
é O (n) (com n / 4 etapas em média), mas O (1) quando index = 0
ou index = list.size() - 1
(nesse caso, você também pode usar addFirst()
e addLast()
/ add()
). Um dos principais benefícios de LinkedList<E>
remove(int index)
é O (n) (com n / 4 etapas em média), mas O (1) quando index = 0
ou index = list.size() - 1
(nesse caso, você também pode usar removeFirst()
e removeLast()
). Um dos principais benefícios de LinkedList<E>
Iterator.remove()
é O (1) . Um dos principais benefícios de LinkedList<E>
ListIterator.add(E element)
é O (1) . Um dos principais benefícios de LinkedList<E>
Nota: Muitas das operações precisam de n / 4 etapas, em média, número constante de etapas no melhor caso (por exemplo, índice = 0) e n / 2 etapas no pior caso (meio da lista)
Para ArrayList<E>
get(int index)
é O (1) . Principal benefício de ArrayList<E>
add(E element)
é O (1) amortizado, mas O (n) na pior das hipóteses, pois a matriz deve ser redimensionada e copiada
add(int index, E element)
é O (n) (com n / 2 passos em média)
remove(int index)
é O (n) (com n / 2 passos em média)
Iterator.remove()
é O (n) (com n / 2 passos em média)
ListIterator.add(E element)
é O (n) (com n / 2 passos em média)
Nota: Muitas das operações precisam de n / 2 etapas, em média, número constante de etapas no melhor caso (final da lista), n etapas no pior caso (início da lista)
LinkedList<E>
permite inserções ou remoções em tempo constante usando iteradores , mas apenas acesso seqüencial aos elementos. Em outras palavras, você pode percorrer a lista para frente ou para trás, mas encontrar uma posição na lista leva um tempo proporcional ao tamanho da lista. Javadoc diz que "as operações indexadas na lista percorrerão a lista do começo ou do fim, o que estiver mais próximo" , então esses métodos são O (n) ( n / 4 passos) em média, embora O (1) para index = 0
.
ArrayList<E>
, por outro lado, permita acesso rápido de leitura aleatória, para que você possa pegar qualquer elemento em tempo constante. Mas adicionar ou remover de qualquer lugar, exceto o final, exige a troca de todos os últimos elementos, seja para fazer uma abertura ou preencher a lacuna. Além disso, se você adicionar mais elementos do que a capacidade da matriz subjacente, uma nova matriz (1,5 vezes o tamanho) será alocada e a matriz antiga será copiada para a nova. Portanto, adicionar a um ArrayList
é O (n) na pior das hipóteses. caso, mas constante, em média.
Portanto, dependendo das operações que você pretende executar, escolha as implementações adequadamente. A iteração sobre qualquer tipo de lista é praticamente igualmente barata. (Iterar sobre um ArrayList
é tecnicamente mais rápido, mas, a menos que você esteja fazendo algo realmente sensível ao desempenho, não se preocupe com isso - as duas são constantes.)
Os principais benefícios do uso de um LinkedList
surgem quando você reutiliza os iteradores existentes para inserir e remover elementos. Essas operações podem ser realizadas em O (1) , alterando apenas a lista localmente. Em uma lista de matrizes, o restante da matriz precisa ser movido (ou seja, copiado). Por outro lado, procurar de uma LinkedList
maneira seguir os links em O (n) ( n / 2 passos) para o pior caso, enquanto que em uma ArrayList
posição desejada pode ser computado matematicamente e acessado em O (1) .
Outro benefício do uso de a LinkedList
surge quando você adiciona ou remove do cabeçalho da lista, pois essas operações são O (1) , enquanto são O (n) para ArrayList
. Observe que ArrayDeque
pode ser uma boa alternativa LinkedList
para adicionar e remover da cabeça, mas não é a List
.
Além disso, se você tiver listas grandes, lembre-se de que o uso de memória também é diferente. Cada elemento de a LinkedList
tem mais sobrecarga, já que os ponteiros para os elementos seguinte e anterior também são armazenados. ArrayLists
não tem essa sobrecarga. No entanto, ArrayLists
ocupe a quantidade de memória alocada para a capacidade, independentemente de os elementos terem sido realmente adicionados.
A capacidade inicial padrão de um ArrayList
é bem pequena (10 de Java 1.4 - 1.8). Mas como a implementação subjacente é uma matriz, ela deverá ser redimensionada se você adicionar muitos elementos. Para evitar o alto custo de redimensionamento quando você sabe que irá adicionar muitos elementos, construa-o ArrayList
com uma capacidade inicial mais alta.