Eu sempre fui o único a usar:
List<String> names = new ArrayList<>();
Uso a interface como o nome do tipo para portabilidade , para que, quando fizer perguntas como essas, possa refazer o meu código.
Quando deve LinkedList
ser utilizado ArrayList
e vice-versa?
java
arraylist
collections
linked-list
sdellysse
fonte
fonte
Respostas:
Resumo
ArrayList
comArrayDeque
é preferível em muitos mais casos de uso do queLinkedList
. Se você não tiver certeza, basta começarArrayList
.LinkedList
eArrayList
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) quandoindex = 0
ouindex = list.size() - 1
(nesse caso, você também pode usargetFirst()
egetLast()
). Um dos principais benefícios deLinkedList<E>
add(int index, E element)
é O (n) (com n / 4 etapas em média), mas O (1) quandoindex = 0
ouindex = list.size() - 1
(nesse caso, você também pode usaraddFirst()
eaddLast()
/add()
). Um dos principais benefícios deLinkedList<E>
remove(int index)
é O (n) (com n / 4 etapas em média), mas O (1) quandoindex = 0
ouindex = list.size() - 1
(nesse caso, você também pode usarremoveFirst()
eremoveLast()
). Um dos principais benefícios deLinkedList<E>
Iterator.remove()
é O (1) . Um dos principais benefícios deLinkedList<E>
ListIterator.add(E element)
é O (1) . Um dos principais benefícios deLinkedList<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 deArrayList<E>
add(E element)
é O (1) amortizado, mas O (n) na pior das hipóteses, pois a matriz deve ser redimensionada e copiadaadd(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) paraindex = 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 umArrayList
é 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 umaLinkedList
maneira seguir os links em O (n) ( n / 2 passos) para o pior caso, enquanto que em umaArrayList
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) paraArrayList
. Observe queArrayDeque
pode ser uma boa alternativaLinkedList
para adicionar e remover da cabeça, mas não é aList
.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-oArrayList
com uma capacidade inicial mais alta.fonte
O(n/2)
ouO(n/4)
. A notação O grande mostra como uma operação é escalada com n maior . e uma operação que precisa den/2
etapas é dimensionada exatamente como uma operação que precisa den
etapas, e é por isso que os somas ou fatores constantes são removidos.O(n/2)
eO(n/4)
são ambos justosO(n)
.LinkedList
eArrayList
têm diferentes fatores constantes de qualquer maneira, portanto, não faria sentido comparar umO(n/2)
de um comO(n/4)
outro, ambos apenas denotam operações de dimensionamento linear.Até agora, ninguém parece ter abordado a área de memória de cada uma dessas listas, além do consenso geral de que a
LinkedList
é "muito mais" do que uma,ArrayList
então fiz um processamento de números para demonstrar exatamente quanto ambas as listas ocupam para N referências nulas.Como as referências são de 32 ou 64 bits (mesmo quando nulas) em seus sistemas relativos, incluí 4 conjuntos de dados para 32 e 64 bits
LinkedLists
eArrayLists
.Nota: Os tamanhos mostrados para as
ArrayList
linhas são para listas aparadas - Na prática, a capacidade da matriz de apoio em umaArrayList
é geralmente maior que a contagem atual de elementos.Nota 2: (obrigado BeeOnRope) Como o CompressedOops agora é padrão a partir do meio do JDK6 e acima, os valores abaixo para máquinas de 64 bits basicamente correspondem aos seus equivalentes de 32 bits, a menos que você o desative especificamente.
O resultado mostra claramente que
LinkedList
é muito mais do que issoArrayList
, especialmente com uma contagem muito alta de elementos. Se a memória é um fator, eviteLinkedLists
.As fórmulas que usei seguem, deixe-me saber se fiz algo errado e vou consertar. 'b' é 4 ou 8 para sistemas de 32 ou 64 bits e 'n' é o número de elementos. Observe que a razão para os mods é porque todos os objetos em java ocupam um espaço múltiplo de 8 bytes, independentemente de todos serem usados ou não.
ArrayList:
ArrayList object header + size integer + modCount integer + array reference + (array oject header + b * n) + MOD(array oject, 8) + MOD(ArrayList object, 8) == 8 + 4 + 4 + b + (12 + b * n) + MOD(12 + b * n, 8) + MOD(8 + 4 + 4 + b + (12 + b * n) + MOD(12 + b * n, 8), 8)
LinkedList:
LinkedList object header + size integer + modCount integer + reference to header + reference to footer + (node object overhead + reference to previous element + reference to next element + reference to element) * n) + MOD(node object, 8) * n + MOD(LinkedList object, 8) == 8 + 4 + 4 + 2 * b + (8 + 3 * b) * n + MOD(8 + 3 * b, 8) * n + MOD(8 + 4 + 4 + 2 * b + (8 + 3 * b) * n + MOD(8 + 3 * b, 8) * n, 8)
fonte
int
, portanto, 4 ou 8 bytes de dados. Na lista vinculada, existem essencialmente 4 "palavras" de sobrecarga. Assim, seu gráfico dá a impressão de que listas vinculadas usam "cinco vezes" o armazenamento de listas de matrizes. Isto está errado. A sobrecarga é de 16 ou 32 bytes por objeto, como um ajuste aditivo, não como um fator de escala.CompressedOops
agora é padrão em todos os JDKs recentes (7, 8 e atualizações de 6 por alguns anos), portanto, 64 bits não fará diferençaArrayList
ouLinkedList
tamanhos, a menos que você tenha desabilitado explicitamente oops compactados para alguma razão.ArrayList
sem especificar uma capacidade inicial, ele ainda usará significativamente menos memória que umLinkedList
.ArrayList
é o que você quer.LinkedList
quase sempre é um bug (desempenho).Por que
LinkedList
é péssimo:ArrayList
fosse usado.ArrayList
, provavelmente será significativamente mais lento.LinkedList
na fonte, porque provavelmente é a escolha errada.fonte
Como alguém que faz engenharia de desempenho operacional em serviços da Web SOA em larga escala há cerca de uma década, eu preferiria o comportamento do LinkedList ao invés de ArrayList. Embora a taxa de transferência no estado estacionário do LinkedList seja pior e, portanto, possa levar à compra de mais hardware - o comportamento do ArrayList sob pressão pode levar os aplicativos em um cluster a expandir suas matrizes em quase sincronicidade e, para tamanhos de matriz grandes, pode levar à falta de capacidade de resposta no aplicativo e uma interrupção, enquanto estiver sob pressão, que é um comportamento catastrófico.
Da mesma forma, você pode obter uma melhor taxa de transferência em um aplicativo a partir do coletor de lixo garantido de taxa de transferência padrão, mas uma vez que você obtém aplicativos java com 10 GB de pilha, pode encerrar o aplicativo por 25 segundos durante um GC completo, causando timeouts e falhas em aplicativos SOA e altera seus SLAs se ocorrer com muita frequência. Embora o coletor do CMS consiga mais recursos e não atinja a mesma taxa de transferência bruta, é uma escolha muito melhor, pois possui latência mais previsível e menor.
ArrayList é apenas uma opção melhor para desempenho se tudo o que você quer dizer com desempenho é taxa de transferência e você pode ignorar a latência. Na minha experiência no trabalho, não posso ignorar a pior latência.
fonte
LinkedList
sempre aloca cinco vezes a memória do que uma matriz simples de referências; portanto, um requerimentoArrayList
temporário de 2,5 vezes ainda consome muito menos memória, mesmo enquanto a memória não é recuperada. Desde alocação grande variedade ignora o espaço Éden, eles não têm qualquer impacto sobre o comportamento GC, a menos que realmente não há memória suficiente, caso em que, aLinkedList
explodiu muito mais cedo ...LinkedList
precisa apenas de um pequeno pedaço de memória livre para alocar o próximo elemento.ArrayList
precisará de um bloco de espaço livre grande e contínuo para alocar a matriz redimensionada. Se o heap for fragmentado, o GC poderá acabar reordenando o heap inteiro apenas para liberar um único bloco de memória adequado.Algoritmos: Notação Big-Oh
As ArrayLists são boas para escrever ou ler muitos ou anexos, mas são ruins para adicionar / remover da frente ou do meio.
fonte
O(1)
. Ele precisa percorrer metade da lista para encontrar o ponto de inserção.LinkedList
éO(1)
se você tiver um iterador na posição de inserção , ou seja,ListIterator.add
é supostamenteO(1)
para aLinkedList
.Sim, eu sei, essa é uma pergunta antiga, mas vou colocar meus dois centavos:
O LinkedList é quase sempre a escolha errada, em termos de desempenho. Existem alguns algoritmos muito específicos nos quais uma LinkedList é solicitada, mas eles são muito, muito raros, e o algoritmo geralmente depende especificamente da capacidade do LinkedList de inserir e excluir elementos no meio da lista de forma relativamente rápida, depois de navegar por lá. com um ListIterator.
Há um caso de uso comum no qual o LinkedList supera o ArrayList: o de uma fila. No entanto, se seu objetivo é desempenho, em vez de LinkedList, considere também usar um ArrayBlockingQueue (se você pode determinar um limite superior do tamanho da sua fila com antecedência e pode alocar toda a memória antecipadamente) ou esta implementação CircularArrayList . (Sim, é de 2001, então você precisará gerá-lo, mas eu tenho índices de desempenho comparáveis aos citados no artigo agora em uma JVM recente)
fonte
ArrayDeque
. docs.oracle.com/javase/6/docs/api/java/util/ArrayDeque.htmlArrayDeque
é mais lento que aLinkedList
menos que todas as operações estejam no mesmo fim. Tudo bem quando usado como uma pilha, mas não cria uma boa fila.ArrayDeque
provavelmente será mais rápido do queStack
quando usado como uma pilha e mais rápido do queLinkedList
quando usado como uma fila.ArrayDeque
documentação.É uma questão de eficiência.
LinkedList
é rápido para adicionar e excluir elementos, mas lento para acessar um elemento específico.ArrayList
é rápido para acessar um elemento específico, mas pode ser lento para adicionar em qualquer extremidade e especialmente lento para excluir no meio.Matriz vs ArrayList vs LinkedList vs Vector vai mais fundo, assim como a Lista vinculada .
fonte
Correto ou incorreto: Por favor, execute o teste localmente e decida por si mesmo!
Editar / Remover é mais rápido
LinkedList
queArrayList
.ArrayList
, suportado porArray
, que precisa ter o dobro do tamanho, é pior em aplicativos de grande volume.Abaixo está o resultado do teste de unidade para cada operação. O tempo é dado em nanossegundos.
Aqui está o código:
fonte
LinkedList
tem muito mais sobrecarga de memória porque para cada elemento existe um objeto de nó com cinco campos. Em muitos sistemas, isso gera 20 bytes de sobrecarga. A sobrecarga média de memória por elementoArrayList
é de uma palavra e meia, que gera 6 bytes e 8 bytes no pior caso.removeIf(element -> condition)
onde ele se encaixa, o que pode ser significativamente mais rápido para umArrayList
, em comparação com o loop e a remoção via iterador, pois não é necessário mudar o restante inteiro para cada elemento individual. Se o desempenho é melhor ou pior do queLinkedList
depende do cenário específico, comoLinkedList
é O (1) em teoria, mas remover apenas um nó requer vários acessos à memória, que podem facilmente exceder o número necessário para aArrayList
remoção de um número significativo de elementos .ArrayList
é essencialmente uma matriz.LinkedList
é implementado como uma lista vinculada dupla.O
get
é bem claro. O (1) paraArrayList
, porqueArrayList
permite acesso aleatório usando o índice. O (n) paraLinkedList
, porque ele precisa encontrar o índice primeiro. Nota: existem versões diferentes deadd
eremove
.LinkedList
é mais rápido em adicionar e remover, mas mais lento em obter. Em resumo,LinkedList
deve ser preferido se:=== ArrayList ===
=== LinkedList ===
adicionar (E e)
add (índice int, elemento E)
Aqui está uma figura de programcreek.com (
add
eremove
é o primeiro tipo, ou seja, adicione um elemento no final da lista e remova o elemento na posição especificada na lista.):fonte
Joshua Bloch, autor do LinkedList:
Link: https://twitter.com/joshbloch/status/583813919019573248
Sinto muito pela resposta por não ser tão informativa quanto as outras respostas, mas achei que seria a mais interessante e auto-explicativa.
fonte
ArrayList
é acessível aleatoriamente, enquantoLinkedList
é muito barato expandir e remover elementos. Para a maioria dos casos, tudoArrayList
bem.A menos que você tenha criado grandes listas e medido um gargalo, provavelmente nunca precisará se preocupar com a diferença.
fonte
O TL; DR, devido à arquitetura moderna do computador,
ArrayList
será significativamente mais eficiente para praticamente qualquer caso de uso possível - e, portanto,LinkedList
deve ser evitado, exceto em casos extremos e muito únicos.Em teoria, o LinkedList possui um O (1) para o
add(E element)
A adição de um elemento no meio de uma lista também deve ser muito eficiente.
A prática é muito diferente, pois o LinkedList é uma estrutura de dados hostis de cache . Do ponto de vista do desempenho - há muito poucos casos em
LinkedList
que o desempenho pode ser melhor do que os compatíveis com o cacheArrayList
.Aqui estão os resultados de um teste de referência, inserindo elementos em locais aleatórios. Como você pode ver - a lista de matrizes é muito mais eficiente, embora em teoria cada inserção no meio da lista exija "mover" os n elementos posteriores da matriz (valores mais baixos são melhores):
Trabalhando em um hardware de última geração (caches maiores e mais eficientes) - os resultados são ainda mais conclusivos:
O LinkedList leva muito mais tempo para realizar o mesmo trabalho. código fonte
Há duas razões principais para isso:
Principalmente - que os nós do
LinkedList
estão espalhados aleatoriamente pela memória. A RAM ("Memória de acesso aleatório") não é realmente aleatória e os blocos de memória precisam ser buscados no cache. Essa operação leva tempo e, quando tais buscas ocorrem com freqüência - as páginas de memória no cache precisam ser substituídas o tempo todo -> Falta de cache -> O cache não é eficiente.ArrayList
os elementos são armazenados na memória contínua - e é exatamente para isso que a arquitetura moderna da CPU está otimizando.Secundário
LinkedList
necessário para manter os ponteiros de retrocesso / avanço, o que significa três vezes o consumo de memória por valor armazenado em comparação comArrayList
.DynamicIntArray , btw, é uma retenção de implementação ArrayList personalizada
Int
(tipo primitivo) e não Objetos - portanto, todos os dados são realmente armazenados adjacentemente - portanto, ainda mais eficientes.Um elemento-chave a ser lembrado é que o custo de buscar o bloco de memória é mais significativo do que o custo de acessar uma única célula de memória. É por isso que o leitor de 1 MB de memória seqüencial é até 400 vezes mais rápido do que ler essa quantidade de dados de diferentes blocos de memória:
Fonte: números de latência que todo programador deve saber
Apenas para tornar o argumento ainda mais claro, verifique a referência de adição de elementos ao início da lista. Este é um caso de uso em que, teoricamente, o
LinkedList
item deve realmente brilhar eArrayList
deve apresentar resultados ruins ou até piores:Nota: esta é uma referência da biblioteca C ++ Std, mas minha experiência anterior mostrou que os resultados em C ++ e Java são muito semelhantes. Código fonte
Copiar um volume sequencial de memória é uma operação otimizada pelas CPUs modernas - mudando a teoria e tornando, de novo,
ArrayList
/Vector
muito mais eficienteCréditos: todos os benchmarks publicados aqui são criados por Kjell Hedström . Ainda mais dados podem ser encontrados em seu blog
fonte
Se o seu código possui
add(0)
eremove(0)
, useLinkedList
ae é mais bonitoaddFirst()
eremoveFirst()
métodos. Caso contrário, useArrayList
.E, é claro, o ImmutableList da Guava é seu melhor amigo.
fonte
Sei que este é um post antigo, mas eu honestamente não posso acreditar que ninguém mencionou que os
LinkedList
implementosDeque
. Basta olhar para os métodos emDeque
(eQueue
); se você quiser uma comparação justa, tente executarLinkedList
contraArrayDeque
e fazer uma comparação de recursos-de-recurso.fonte
Aqui está a notação Big-O em ambos
ArrayList
eLinkedList
e tambémCopyOnWrite-ArrayList
:ArrayList
LinkedList
CopyOnWrite-ArrayList
Com base nisso, você deve decidir o que escolher. :)
fonte
LinkedList.add()
, embora a maioria das respostas aqui diga isso.Vamos comparar o LinkedList e o ArrayList abaixo dos parâmetros:
1. Implementação
2. Desempenho
operação get (int index) ou de pesquisa
A razão por trás do ArrayList ser mais rápido que o LinkedList é que o ArrayList usa um sistema baseado em índice para seus elementos, pois internamente usa uma estrutura de dados da matriz, por outro lado,
O LinkedList não fornece acesso baseado em índice para seus elementos, pois itera do começo ou do fim (o que estiver mais próximo) para recuperar o nó no índice de elemento especificado.
operação insert () ou add (Object)
operação remover (int)
A operação de remoção no LinkedList geralmente é igual à ArrayList, ou seja, O (n).
3. Iterador Reverso
4. Capacidade inicial
5. Sobrecarga de memória
Fonte
fonte
Eu costumo usar um sobre o outro com base nas complexidades de tempo das operações que eu executaria nessa lista específica.
fonte
Além dos outros bons argumentos acima, você deve observar a interface de
ArrayList
implementosRandomAccess
, enquantoLinkedList
implementaQueue
.Então, de alguma forma, eles abordam problemas um pouco diferentes, com diferenças de eficiência e comportamento (consulte a lista de métodos).
fonte
Depende de quais operações você fará mais na lista.
ArrayList
é mais rápido acessar um valor indexado. É muito pior ao inserir ou excluir objetos.Para saber mais, leia qualquer artigo que fale sobre a diferença entre matrizes e listas vinculadas.
fonte
Uma lista de matrizes é essencialmente uma matriz com métodos para adicionar itens, etc. (e você deve usar uma lista genérica). É uma coleção de itens que podem ser acessados através de um indexador (por exemplo [0]). Implica uma progressão de um item para o próximo.
Uma lista vinculada especifica uma progressão de um item para o próximo (Item a -> item b). Você pode obter o mesmo efeito com uma lista de matrizes, mas uma lista vinculada diz absolutamente que item deve seguir o anterior.
fonte
Consulte os Tutoriais Java - Implementações da lista .
fonte
Um recurso importante de uma lista vinculada (que eu não li em outra resposta) é a concatenação de duas listas. Com uma matriz, isso é O (n) (+ sobrecarga de algumas realocações) com uma lista vinculada, isso é apenas O (1) ou O (2) ;-)
Importante : Para Java,
LinkedList
isso não é verdade! Consulte Existe um método de concat rápido para lista vinculada em Java?fonte
next
de uma lista para o primeiro nó na segunda lista. A única maneira é usar oaddAll()
que adiciona elementos sequencialmente, embora seja melhor do que percorrer e chamaradd()
cada elemento. Para fazer isso rapidamente em O (1), você precisaria de uma classe de composição (como org.apache.commons.collections.collection.CompositeCollection), mas isso funcionaria para qualquer tipo de lista / coleção.ArrayList e LinkedList têm seus próprios prós e contras.
ArrayList usa o endereço de memória contíguo em comparação com o LinkedList, que usa ponteiros para o próximo nó. Portanto, quando você deseja procurar um elemento em um ArrayList, é mais rápido que fazer iterações com o LinkedList.
Por outro lado, a inserção e exclusão em uma LinkedList são muito mais fáceis, porque você só precisa alterar os ponteiros, enquanto uma ArrayList implica o uso da operação shift para qualquer inserção ou exclusão.
Se você tiver operações de recuperação frequentes no seu aplicativo, use um ArrayList. Se você tiver inserção e exclusão freqüentes, use um LinkedList.
fonte
Li as respostas, mas há um cenário em que sempre uso uma LinkedList sobre uma ArrayList que quero compartilhar para ouvir opiniões:
Toda vez que eu tinha um método que retorna uma lista de dados obtidos de um banco de dados, eu sempre uso um LinkedList.
Minha lógica era que, porque é impossível saber exatamente quantos resultados estou obtendo, não haverá desperdício de memória (como em ArrayList com a diferença entre a capacidade e o número real de elementos) e não haveria desperdício de tempo tentando duplicar a capacidade.
Quanto a ArrayList, concordo que pelo menos você sempre deve usar o construtor com a capacidade inicial, para minimizar ao máximo a duplicação das matrizes.
fonte
ArrayList
eLinkedList
os implementos,List interface
seus métodos e resultados são quase idênticos. No entanto, existem poucas diferenças entre eles que melhoram um ao outro, dependendo do requisito.ArrayList Vs LinkedList
1) a
Search:
ArrayList
operação de pesquisa é bastante rápida em comparação com aLinkedList
operação de pesquisa.get(int index)
inArrayList
fornece o desempenho deO(1)
enquanto oLinkedList
desempenho éO(n)
.Reason:
ArrayList
mantém um sistema baseado em índice para seus elementos, pois usa implicitamente a estrutura de dados da matriz, o que torna mais rápido a pesquisa de um elemento na lista. Por outro lado,LinkedList
implementa lista duplamente vinculada, que requer a passagem por todos os elementos para pesquisar um elemento.2) a
Deletion:
LinkedList
operação de remoção forneceO(1)
desempenho, enquantoArrayList
fornece desempenho variável:O(n)
na pior das hipóteses (ao remover o primeiro elemento) eO(1)
na melhor das hipóteses (ao remover o último elemento).Razão: Cada elemento do LinkedList mantém dois ponteiros (endereços) que apontam para os dois elementos vizinhos na lista. Portanto, a remoção requer apenas alteração na localização do ponteiro nos dois nós vizinhos (elementos) do nó que será removido. Enquanto Em ArrayList, todos os elementos precisam ser deslocados para preencher o espaço criado pelo elemento removido.
3)
Inserts Performance:
LinkedList
método add dáO(1)
o desempenho enquantoArrayList
dáO(n)
no pior caso. O motivo é o mesmo que o explicado para remover.4)
Memory Overhead:
ArrayList
mantém índices e dados de elementos enquantoLinkedList
mantém dados de elementos e dois ponteiros para nós vizinhosExistem poucas semelhanças entre essas classes, que são as seguintes:
iterator
elistIterator
retornado por essas classes sãofail-fast
(se a lista for estruturalmente modificada a qualquer momento após a criação do iterador, de qualquer forma, exceto pelositerator’s
próprios métodos de remoção ou adição, o iteradorthrow
aConcurrentModificationException
).Quando usar o LinkedList e quando usar o ArrayList?
(O(1))
emLinkedList
comparação comArrayList(O(n))
.get method
operações de pesquisa ( ) são rápidas,Arraylist (O(1))
mas não emLinkedList (O(n))
fonte
A operação get (i) no ArrayList é mais rápida que no LinkedList, porque:
ArrayList: implementação de matriz redimensionável da interface List
LinkedList: implementação de lista duplamente vinculada das interfaces List e Deque
As operações indexadas na lista percorrerão a lista desde o início ou o final, o que estiver mais próximo do índice especificado.
fonte
1) Estrutura de dados subjacente
A primeira diferença entre ArrayList e LinkedList vem com o fato de que ArrayList é apoiado por Array enquanto LinkedList é apoiado por LinkedList. Isso levará a outras diferenças no desempenho.
2) O LinkedList implementa o Deque
Outra diferença entre ArrayList e LinkedList é que, além da interface List, o LinkedList também implementa a interface Deque, que fornece as operações de primeiro a entrar para adicionar () e poll () e várias outras funções de Deque. 3) Adicionando elementos no ArrayList O elemento Add no ArrayList é a operação O (1) se não acionar o redimensionamento do Array; nesse caso, ele se tornará O (log (n)). Por outro lado, anexando um elemento no LinkedList é uma operação O (1), pois não requer nenhuma navegação.
4) Removendo um elemento de uma posição
Para remover um elemento de um índice específico, por exemplo, chamando remove (index), ArrayList executa uma operação de cópia que o aproxima de O (n), enquanto o LinkedList precisa passar para aquele ponto que também o torna O (n / 2) , pois ele pode percorrer de qualquer direção com base na proximidade.
5) Iterando sobre ArrayList ou LinkedList
A iteração é a operação O (n) para o LinkedList e o ArrayList em que n é o número de um elemento.
6) Recuperando elemento de uma posição
A operação get (index) é O (1) em ArrayList enquanto seu O (n / 2) em LinkedList, pois precisa percorrer até essa entrada. Embora, na notação O grande, O (n / 2) seja apenas O (n) porque ignoramos constantes lá.
7) Memória
O LinkedList usa um objeto wrapper, Entry, que é uma classe aninhada estática para armazenar dados e dois nós próximos e anteriores, enquanto o ArrayList apenas armazena dados no Array.
Portanto, o requisito de memória parece menos no caso de ArrayList do que no LinkedList, exceto no caso em que Array executa a operação de redimensionar tamanho quando copia o conteúdo de um Array para outro.
Se a matriz for grande o suficiente, poderá levar muita memória nesse momento e disparar a coleta de lixo, o que pode diminuir o tempo de resposta.
De todas as diferenças acima entre ArrayList e LinkedList, parece que ArrayList é a melhor escolha que o LinkedList em quase todos os casos, exceto quando você faz uma operação add () frequente do que remove () ou get ().
É mais fácil modificar uma lista vinculada do que ArrayList, especialmente se você estiver adicionando ou removendo elementos do início ou do fim, porque a lista vinculada mantém internamente referências dessas posições e elas são acessíveis em O (1).
Em outras palavras, você não precisa percorrer a lista vinculada para alcançar a posição em que deseja adicionar elementos; nesse caso, a adição se torna operação O (n). Por exemplo, inserindo ou excluindo um elemento no meio de uma lista vinculada.
Na minha opinião, use ArrayList sobre LinkedList para a maioria dos propósitos práticos em Java.
fonte
Um dos testes que vi aqui apenas realiza o teste uma vez. Mas o que eu notei é que você precisa executar esses testes várias vezes e, eventualmente, o tempo deles irá convergir. Basicamente, a JVM precisa se aquecer. Para o meu caso de uso específico, eu precisava adicionar / remover itens a uma lista que aumenta para cerca de 500 itens. Nos meus testes,
LinkedList
saiu mais rápido,LinkedList
chegando a cerca de 50.000 NS eArrayList
chegando a cerca de 90.000 NS ... mais ou menos. Veja o código abaixo.fonte
Remove () e insert () têm uma eficiência de tempo de execução de O (n) para ArrayLists e LinkedLists. No entanto, a razão por trás do tempo de processamento linear vem de duas razões muito diferentes:
Em um ArrayList, você chega ao elemento em O (1), mas na verdade a remoção ou a inserção de algo o torna O (n) porque todos os seguintes elementos precisam ser alterados.
Em um LinkedList, é necessário O (n) para realmente chegar ao elemento desejado, porque temos que começar desde o início até atingir o índice desejado. Na verdade, remover ou inserir é constante, porque precisamos alterar apenas 1 referência para remove () e 2 referências para insert ().
Qual dos dois é mais rápido para inserir e remover depende de onde isso acontece. Se estivermos mais próximos do início, o LinkedList será mais rápido, porque precisamos passar por relativamente poucos elementos. Se estivermos mais perto do final, um ArrayList será mais rápido, porque chegamos lá em tempo constante e só precisamos alterar os poucos elementos restantes que o seguem. Quando feito precisamente no meio, o LinkedList será mais rápido porque passar por n elementos é mais rápido que mover n valores.
Bônus: Embora não haja como criar esses dois métodos O (1) para um ArrayList, na verdade há um modo de fazer isso no LinkedLists. Digamos que queremos passar por toda a Lista removendo e inserindo elementos em nosso caminho. Normalmente, você começaria do início para cada elemento usando o LinkedList; também poderíamos "salvar" o elemento atual em que estamos trabalhando com um Iterador. Com a ajuda do Iterator, obtemos uma eficiência O (1) para remover () e insert () ao trabalhar em uma LinkedList. Tornando-o o único benefício de desempenho, eu sei onde um LinkedList é sempre melhor que um ArrayList.
fonte
ArrayList estende AbstractList e implementa a Interface da lista. ArrayList é uma matriz dinâmica.
Pode-se dizer que foi basicamente criado para superar as desvantagens de matrizes.
A classe LinkedList estende AbstractSequentialList e implementa a interface List, Deque e Queue.
O desempenho
arraylist.get()
é O (1) enquantolinkedlist.get()
O (n)arraylist.add()
é O (1) elinkedlist.add()
é 0 (1)arraylist.contains()
é O (n) elinkedlist.contains()
é O (n)arraylist.next()
é O (1) elinkedlist.next()
é O (1)arraylist.remove()
é O (n) Considerando quelinkedlist.remove()
é O (1)Na matriz
iterator.remove()
é O (n)Enquanto Na lista vinculada
iterator.remove()
é O (1)fonte