Siempre he sido uno para usar simplemente:
List<String> names = new ArrayList<>();
Utilizo la interfaz como el nombre del tipo para la portabilidad , de modo que cuando hago preguntas como estas, puedo modificar mi código.
¿Cuándo debe LinkedList
usarse ArrayList
y viceversa?
java
arraylist
collections
linked-list
sdellysse
fuente
fuente
Respuestas:
El resumen
ArrayList
conArrayDeque
es preferible en muchos más casos de uso queLinkedList
. Si no está seguro, simplemente comience conArrayList
.LinkedList
yArrayList
son dos implementaciones diferentes de la interfaz List.LinkedList
lo implementa con una lista doblemente vinculada.ArrayList
lo implementa con una matriz de redimensionamiento dinámico.Al igual que con la lista estándar vinculada y las operaciones de matriz, los diversos métodos tendrán diferentes tiempos de ejecución algorítmicos.
por
LinkedList<E>
get(int index)
es O (n) (con n / 4 pasos en promedio), pero O (1) cuándoindex = 0
oindex = list.size() - 1
(en este caso, también puede usargetFirst()
ygetLast()
). Uno de los principales beneficios deLinkedList<E>
add(int index, E element)
es O (n) (con n / 4 pasos en promedio), pero O (1) cuandoindex = 0
oindex = list.size() - 1
(en este caso, también puede usaraddFirst()
yaddLast()
/add()
). Uno de los principales beneficios deLinkedList<E>
remove(int index)
es O (n) (con n / 4 pasos en promedio), pero O (1) cuándoindex = 0
oindex = list.size() - 1
(en este caso, también puede usarremoveFirst()
yremoveLast()
). Uno de los principales beneficios deLinkedList<E>
Iterator.remove()
es O (1) . Uno de los principales beneficios deLinkedList<E>
ListIterator.add(E element)
es O (1) . Uno de los principales beneficios deLinkedList<E>
Nota: Muchas de las operaciones necesitan n / 4 pasos en promedio, un número constante de pasos en el mejor de los casos (por ejemplo, índice = 0) y n / 2 pasos en el peor de los casos (en el medio de la lista)
por
ArrayList<E>
get(int index)
es O (1) . Principal beneficio deArrayList<E>
add(E element)
es O (1) amortizado, pero O (n) en el peor de los casos ya que la matriz debe ser redimensionada y copiadaadd(int index, E element)
es O (n) (con n / 2 pasos en promedio)remove(int index)
es O (n) (con n / 2 pasos en promedio)Iterator.remove()
es O (n) (con n / 2 pasos en promedio)ListIterator.add(E element)
es O (n) (con n / 2 pasos en promedio)Nota: Muchas de las operaciones necesitan n / 2 pasos en promedio, un número constante de pasos en el mejor de los casos (final de la lista), n pasos en el peor de los casos (inicio de la lista)
LinkedList<E>
permite inserciones o eliminaciones de tiempo constante utilizando iteradores , pero solo acceso secuencial de elementos. En otras palabras, puede caminar la lista hacia adelante o hacia atrás, pero encontrar una posición en la lista lleva tiempo proporcional al tamaño de la lista. Javadoc dice que "las operaciones que se indexan en la lista atravesarán la lista desde el principio o el final, lo que esté más cerca" , por lo que esos métodos son O (n) ( n / 4 pasos) en promedio, aunque O (1) paraindex = 0
.ArrayList<E>
, por otro lado, permita un acceso de lectura aleatorio rápido, para que pueda tomar cualquier elemento en tiempo constante. Pero agregar o eliminar de cualquier lugar que no sea el final requiere cambiar todos los últimos elementos, ya sea para hacer una abertura o llenar el vacío. Además, si agrega más elementos que la capacidad de la matriz subyacente, se asigna una nueva matriz (1,5 veces el tamaño) y la matriz anterior se copia en la nueva, por lo que agregar a anArrayList
es O (n) en el peor de los casos caso pero constante en promedio.Por lo tanto, dependiendo de las operaciones que intente hacer, debe elegir las implementaciones en consecuencia. Iterar sobre cualquier tipo de Lista es prácticamente igual de barato. (Iterar sobre un
ArrayList
es técnicamente más rápido, pero a menos que esté haciendo algo realmente sensible al rendimiento, no debe preocuparse por esto, ambos son constantes).Los principales beneficios de usar un
LinkedList
surgen cuando reutiliza iteradores existentes para insertar y eliminar elementos. Estas operaciones se pueden hacer en O (1) cambiando la lista solo localmente. En una lista de matriz, el resto de la matriz debe moverse (es decir, copiarse). Por otro lado, buscar en unLinkedList
medio siguiendo los enlaces en O (n) ( n / 2 pasos) para el peor de los casos, mientras que en unaArrayList
posición deseada se puede calcular matemáticamente y acceder a ella en O (1) .Otro beneficio de usar un
LinkedList
surgir cuando agrega o elimina del encabezado de la lista, ya que esas operaciones son O (1) , mientras que son O (n) paraArrayList
. Tenga en cuenta queArrayDeque
puede ser una buena alternativaLinkedList
para agregar y quitar de la cabeza, pero no es unList
.Además, si tiene listas grandes, tenga en cuenta que el uso de la memoria también es diferente. Cada elemento de a
LinkedList
tiene más sobrecarga ya que también se almacenan los punteros a los elementos siguientes y anteriores.ArrayLists
No tengo esta sobrecarga. Sin embargo,ArrayLists
tome tanta memoria como se asigne para la capacidad, independientemente de si los elementos se han agregado realmente.La capacidad inicial predeterminada de un
ArrayList
es bastante pequeña (10 de Java 1.4 - 1.8). Pero dado que la implementación subyacente es una matriz, se debe cambiar el tamaño de la matriz si agrega muchos elementos. Para evitar el alto costo de cambiar el tamaño cuando sabe que va a agregar muchos elementos, construyaArrayList
con una capacidad inicial más alta.fuente
O(n/2)
oO(n/4)
. La notación O grande le dice cómo una operación escala con una n mayor . y una operación que necesitan/2
pasos se escala exactamente como una operación que necesitan
pasos, razón por la cual se eliminan los sumandos o factores constantes.O(n/2)
yO(n/4)
son ambos justosO(n)
.LinkedList
yArrayList
tener diferentes factores constantes de todos modos, por lo que no tendría sentido compararO(n/2)
uno de uno con otroO(n/4)
del otro, ambos solo denotan operaciones de escala lineal.Hasta el momento, nadie parece haber abordado la huella de memoria de cada una de estas listas, además del consenso general de que a
LinkedList
es "mucho más" que un,ArrayList
así que hice algunos cálculos numéricos para demostrar exactamente cuánto ocupan ambas listas para N referencias nulas.Como las referencias son de 32 o 64 bits (incluso cuando son nulas) en sus sistemas relativos, he incluido 4 conjuntos de datos para 32 y 64 bits
LinkedLists
yArrayLists
.Nota: Los tamaños que se muestran para las
ArrayList
líneas son para listas recortadas : en la práctica, la capacidad de la matriz de respaldo enArrayList
general es mayor que su recuento de elementos actual.Nota 2: (gracias BeeOnRope) Como CompressedOops está predeterminado ahora desde mediados de JDK6 en adelante, los valores a continuación para máquinas de 64 bits básicamente coincidirán con sus contrapartes de 32 bits, a menos que, por supuesto, lo desactive específicamente.
El resultado muestra claramente que
LinkedList
es mucho más que esoArrayList
, especialmente con un recuento de elementos muy alto. Si la memoria es un factor, manténgase alejadoLinkedLists
.Las fórmulas que utilicé siguen, avíseme si he hecho algo mal y lo arreglaré. 'b' es 4 u 8 para sistemas de 32 o 64 bits, y 'n' es el número de elementos. Tenga en cuenta que la razón de las modificaciones es porque todos los objetos en Java ocuparán un espacio múltiple de 8 bytes, independientemente de si se usa o no.
Lista de arreglo:
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)
Lista enlazada:
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)
fuente
int
, por lo que 4 u 8 bytes de datos. En la lista vinculada, hay esencialmente 4 "palabras" de sobrecarga. Por lo tanto, su gráfico da la impresión de que las listas vinculadas usan "cinco veces" el almacenamiento de listas de matrices. Esto está mal. La sobrecarga es de 16 o 32 bytes por objeto, como un ajuste aditivo, no un factor de escala.CompressedOops
es por defecto ahora en todos los JDK recientes (7, 8 y actualizaciones de 6 durante unos años), de modo de 64 bits no hará una diferencia enArrayList
oLinkedList
tamaños, a menos que haya desactivado de forma explícita Uy comprimido para alguna razón.ArrayList
sin especificar una capacidad inicial, seguirá utilizando una cantidad de memoria significativamente menor que aLinkedList
.ArrayList
es lo que quieresLinkedList
casi siempre es un error (de rendimiento).Por qué
LinkedList
apesta:ArrayList
se usaran.ArrayList
, probablemente será significativamente más lento de todos modos.LinkedList
en la fuente porque probablemente sea la elección incorrecta.fuente
Como alguien que ha estado haciendo ingeniería de rendimiento operativo en servicios web SOA a gran escala durante aproximadamente una década, preferiría el comportamiento de LinkedList sobre ArrayList. Si bien el rendimiento en estado estable de LinkedList es peor y, por lo tanto, podría conducir a la compra de más hardware, el comportamiento de ArrayList bajo presión podría llevar a que las aplicaciones en un clúster expandan sus matrices casi sincrónicamente y para tamaños de matriz grandes podría provocar una falta de capacidad de respuesta en la aplicación y un corte de energía, bajo presión, que es un comportamiento catastrófico.
Del mismo modo, puede obtener un mejor rendimiento en una aplicación desde el recolector de basura con rendimiento predeterminado, pero una vez que obtiene aplicaciones Java con montones de 10 GB, puede terminar bloqueando la aplicación durante 25 segundos durante un GC completo que causa tiempos de espera y fallas en las aplicaciones SOA y sopla sus SLA si ocurre con demasiada frecuencia. Aunque el recopilador de CMS toma más recursos y no logra el mismo rendimiento bruto, es una opción mucho mejor porque tiene una latencia más predecible y más pequeña.
ArrayList es solo una mejor opción para el rendimiento si todo lo que quiere decir con rendimiento es rendimiento y puede ignorar la latencia. En mi experiencia en mi trabajo no puedo ignorar la peor latencia.
fuente
LinkedList
siempre asigna cinco veces la memoria que un conjunto simple de referencias, por lo que unArrayList
requerimiento temporal de 2.5 veces todavía consume mucha menos memoria, incluso cuando la memoria no se recupera. Dado que la asignación de matriz grande omite el espacio de Eden, no tienen ningún impacto en el comportamiento de GC, a menos que realmente no haya suficiente memoria, en cuyo caso,LinkedList
explotaron mucho antes ...LinkedList
solo necesita un pequeño trozo de memoria libre para asignar al siguiente elemento.ArrayList
necesitará un bloque de espacio libre grande y continuo para asignar la matriz redimensionada. Si el montón se fragmenta, GC podría terminar reordenando todo el montón solo para liberar un bloque de memoria adecuado.Algoritmos: notación Big-Oh
Las ArrayLists son buenas para escribir una vez, leer muchas o anexos, pero son malas para agregar / quitar desde el frente o en el medio.
fuente
O(1)
. Tiene que recorrer la mitad de la lista para encontrar el punto de inserción.LinkedList
esO(1)
si tiene un iterador en la posición de inserción ,ListIterator.add
es decir, supuestamente esO(1)
para aLinkedList
.Sí, lo sé, esta es una pregunta antigua, pero arrojaré mis dos centavos:
LinkedList es casi siempre la elección incorrecta, en cuanto al rendimiento. Hay algunos algoritmos muy específicos en los que se requiere LinkedList, pero son muy, muy raros y el algoritmo generalmente dependerá específicamente de la capacidad de LinkedList para insertar y eliminar elementos en el medio de la lista relativamente rápido, una vez que haya navegado allí. con un ListIterator.
Hay un caso de uso común en el que LinkedList supera a ArrayList: el de una cola. Sin embargo, si su objetivo es el rendimiento, en lugar de LinkedList, también debería considerar usar un ArrayBlockingQueue (si puede determinar un límite superior en el tamaño de la cola con anticipación y puede permitirse asignar toda la memoria por adelantado), o esta implementación CircularArrayList . (Sí, es de 2001, por lo que deberá generarlo, pero obtuve índices de rendimiento comparables a lo que se cita en el artículo en una JVM reciente)
fuente
ArrayDeque
. docs.oracle.com/javase/6/docs/api/java/util/ArrayDeque.htmlArrayDeque
es más lento que aLinkedList
menos que todas las operaciones estén en el mismo extremo. Está bien cuando se usa como una pila, pero no hace una buena cola.ArrayDeque
es probable que sea más rápido queStack
cuando se usa como una pila, y más rápido queLinkedList
cuando se usa como una cola.ArrayDeque
documentación.Es una pregunta de eficiencia.
LinkedList
es rápido para agregar y eliminar elementos, pero lento para acceder a un elemento específico.ArrayList
es rápido para acceder a un elemento específico, pero puede ser lento para agregar a cualquiera de los extremos, y especialmente lento para eliminar en el medio.Array vs ArrayList vs LinkedList vs Vector va más en profundidad, al igual que Linked List .
fuente
Correcto o incorrecto: ejecute la prueba localmente y decida por usted mismo.
Editar / Eliminar es más rápido
LinkedList
queArrayList
.ArrayList
, respaldado porArray
, que debe ser el doble del tamaño, es peor en aplicaciones de gran volumen.A continuación se muestra el resultado de la prueba unitaria para cada operación. El tiempo se da en nanosegundos.
Aquí está el código:
fuente
LinkedList
tiene mucha más sobrecarga de memoria porque para cada elemento hay un objeto de nodo con cinco campos. En muchos sistemas que genera 20 bytes de sobrecarga. La sobrecarga de memoria promedio por elementoArrayList
es de una palabra y media, que hace 6 bytes y 8 bytes en el peor de los casos.removeIf(element -> condition)
donde encaja, que puede ser significativamente más rápido para unArrayList
, en comparación con el bucle y la eliminación a través del iterador, ya que no es necesario cambiar todo el resto para cada elemento individual. Si esto funciona mejor o peor de lo queLinkedList
depende del escenario particular, como aLinkedList
es O (1) en teoría, pero eliminar solo un nodo requiere varios accesos a la memoria, que pueden exceder fácilmente el número necesario paraArrayList
eliminar un número significativo de elementos .ArrayList
Es esencialmente una matriz.LinkedList
se implementa como una lista de doble enlace.El
get
es bastante claro. O (1) paraArrayList
, porqueArrayList
permite el acceso aleatorio usando el índice. O (n) paraLinkedList
, porque primero necesita encontrar el índice. Nota: hay diferentes versiones deadd
yremove
.LinkedList
es más rápido en agregar y quitar, pero más lento en obtener. En resumen,LinkedList
debe preferirse si:=== ArrayList ===
=== LinkedList ===
agregar (E e)
add (int int, elemento E)
Aquí hay una figura de programcreek.com (
add
yremove
son el primer tipo, es decir, agregue un elemento al final de la lista y elimine el elemento en la posición especificada en la lista):fuente
Joshua Bloch, el autor de LinkedList:
Enlace: https://twitter.com/joshbloch/status/583813919019573248
Lamento la respuesta por no ser tan informativa como las otras respuestas, pero pensé que sería la más interesante y explicativa.
fuente
ArrayList
es accesible al azar, mientras queLinkedList
es realmente barato expandir y eliminar elementos. Para la mayoría de los casos,ArrayList
está bien.A menos que haya creado listas grandes y haya medido un cuello de botella, probablemente nunca tendrá que preocuparse por la diferencia.
fuente
TL; DR debido a la arquitectura moderna de la computadora,
ArrayList
será significativamente más eficiente para casi cualquier posible caso de uso, y porLinkedList
lo tanto debe evitarse excepto algunos casos muy únicos y extremos.En teoría, LinkedList tiene un O (1) para el
add(E element)
También agregar un elemento en el medio de una lista debería ser muy eficiente.
La práctica es muy diferente, ya que LinkedList es una estructura de datos hostiles de caché . Desde el punto de vista del rendimiento: hay muy pocos casos en los que
LinkedList
podría tener un mejor rendimiento que el compatible con cachéArrayList
.Estos son los resultados de una prueba de referencia que inserta elementos en ubicaciones aleatorias. Como puede ver, la lista de la matriz es mucho más eficiente, aunque en teoría cada inserción en el medio de la lista requerirá "mover" los n elementos posteriores de la matriz (los valores más bajos son mejores):
Trabajando en un hardware de última generación (cachés más grandes y más eficientes): los resultados son aún más concluyentes:
LinkedList tarda mucho más tiempo en realizar el mismo trabajo. código fuente
Existen dos motivos principales para esto:
Principalmente : que los nodos del
LinkedList
están dispersos aleatoriamente en la memoria. La RAM ("Memoria de acceso aleatorio") no es realmente aleatoria y los bloques de memoria deben recuperarse en la memoria caché. Esta operación lleva tiempo, y cuando tales recuperaciones ocurren con frecuencia: las páginas de memoria en la memoria caché deben reemplazarse todo el tiempo -> La memoria caché falla -> La memoria caché no es eficiente.ArrayList
los elementos se almacenan en la memoria continua, que es exactamente para lo que está optimizando la arquitectura moderna de la CPU.Se
LinkedList
requiere secundaria para mantener apuntadores hacia atrás / adelante, lo que significa 3 veces el consumo de memoria por valor almacenado en comparación conArrayList
.DynamicIntArray , por cierto, es una implementación de ArrayList personalizada que contiene
Int
(tipo primitivo) y no Objetos, por lo tanto, todos los datos se almacenan de forma adyacente, por lo tanto, son aún más eficientes.Un elemento clave para recordar es que el costo de recuperar el bloque de memoria es más significativo que el costo de acceder a una sola celda de memoria. Es por eso que el lector de 1 MB de memoria secuencial es hasta x400 veces más rápido que leer esta cantidad de datos de diferentes bloques de memoria:
Fuente: Números de latencia que todo programador debe saber
Solo para aclarar el punto, verifique el punto de referencia de agregar elementos al comienzo de la lista. Este es un caso de uso donde, en teoría,
LinkedList
debería brillar realmente, yArrayList
debería presentar resultados pobres o incluso peores:Nota: este es un punto de referencia de C ++ Std lib, pero mi experiencia previa mostró que los resultados de C ++ y Java son muy similares. Código fuente
Copiar una gran cantidad de memoria secuencial es una operación optimizada por las CPU modernas, que cambia la teoría y hace que, de nuevo,
ArrayList
/ seaVector
mucho más eficienteCréditos: todos los puntos de referencia publicados aquí son creados por Kjell Hedström . Incluso se pueden encontrar más datos en su blog
fuente
Si su código tiene
add(0)
yremove(0)
, useLinkedList
ay es más bonitoaddFirst()
y susremoveFirst()
métodos. De lo contrario, useArrayList
.Y, por supuesto, la guayaba 's ImmutableList es su mejor amigo.
fuente
Sé que esta es una publicación antigua, pero sinceramente, no puedo creer que nadie haya mencionado que
LinkedList
implementeDeque
. Solo mire los métodos enDeque
(yQueue
); si quieres una comparación justa, intente ejecutarLinkedList
en contraArrayDeque
y hacer una comparación de características para la función.fuente
Aquí está la notación Big-O en ambos
ArrayList
yLinkedList
y tambiénCopyOnWrite-ArrayList
:Lista de arreglo
Lista enlazada
CopyOnWrite-ArrayList
En función de estos, debe decidir qué elegir. :)
fuente
LinkedList.add()
, aunque la mayoría de las respuestas aquí lo dicen.Comparemos los parámetros debajo de LinkedList y ArrayList wrt a continuación:
1. Implementación
2. Rendimiento
get (int index) u operación de búsqueda
La razón por la que ArrayList es más rápido que LinkedList es que ArrayList usa un sistema basado en índices para sus elementos, ya que internamente usa una estructura de datos de matriz, por otro lado,
LinkedList no proporciona acceso basado en índices para sus elementos, ya que itera desde el principio o el final (lo que esté más cerca) para recuperar el nodo en el índice del elemento especificado.
operación insert () o add (Object)
operación remove (int)
La operación de eliminación en LinkedList es generalmente la misma que ArrayList, es decir, O (n).
3. Iterador inverso
4. Capacidad inicial
5. Memoria de arriba
Fuente
fuente
Por lo general, uso uno sobre el otro según las complejidades de tiempo de las operaciones que realizaría en esa Lista en particular.
fuente
Además de los otros buenos argumentos anteriores, debe observar la interfaz de
ArrayList
implementosRandomAccess
, mientras que losLinkedList
implementosQueue
.Entonces, de alguna manera abordan problemas ligeramente diferentes, con diferencias de eficiencia y comportamiento (vea su lista de métodos).
fuente
Depende de qué operaciones realizará más en la Lista.
ArrayList
es más rápido acceder a un valor indexado. Es mucho peor al insertar o eliminar objetos.Para obtener más información, lea cualquier artículo que hable sobre la diferencia entre las matrices y las listas vinculadas.
fuente
Una lista de matriz es esencialmente una matriz con métodos para agregar elementos, etc. (y debería usar una lista genérica en su lugar). Es una colección de elementos a los que se puede acceder a través de un indexador (por ejemplo [0]). Implica una progresión de un elemento al siguiente.
Una lista vinculada especifica una progresión de un elemento al siguiente (Elemento a -> elemento b). Puede obtener el mismo efecto con una lista de matriz, pero una lista vinculada dice absolutamente qué elemento se supone que debe seguir al anterior.
fuente
Consulte los Tutoriales de Java - Implementaciones de listas .
fuente
Una característica importante de una lista vinculada (que no leí en otra respuesta) es la concatenación de dos listas. Con una matriz, esto es O (n) (+ gastos generales de algunas reasignaciones) con una lista vinculada, esto es solo O (1) u O (2) ;-)
Importante : ¡Para Java
LinkedList
esto no es cierto! Consulte ¿Existe un método rápido de concat para la lista vinculada en Java?fuente
next
desde una lista al primer nodo en la segunda lista. La única forma es usar eladdAll()
que agrega elementos secuencialmente, aunque es mejor que recorrer y llamaradd()
a cada elemento. Para hacer esto rápidamente en O (1) necesitaría una clase de composición (como org.apache.commons.collections.collection.CompositeCollection) pero luego esto funcionaría para cualquier tipo de Lista / Colección.ArrayList y LinkedList tienen sus propios pros y contras.
ArrayList usa una dirección de memoria contigua en comparación con LinkedList que usa punteros hacia el siguiente nodo. Entonces, cuando desea buscar un elemento en una ArrayList es más rápido que hacer n iteraciones con LinkedList.
Por otro lado, la inserción y eliminación en una LinkedList son mucho más fáciles porque solo tiene que cambiar los punteros, mientras que una ArrayList implica el uso de la operación shift para cualquier inserción o eliminación.
Si tiene operaciones de recuperación frecuentes en su aplicación, use una ArrayList. Si tiene una inserción y eliminación frecuente, use LinkedList.
fuente
He leído las respuestas, pero hay un escenario en el que siempre uso una LinkedList sobre una ArrayList que quiero compartir para escuchar opiniones:
Cada vez que tenía un método que devuelve una lista de datos obtenidos de una base de datos, siempre uso un LinkedList.
Mi justificación fue que, debido a que es imposible saber exactamente cuántos resultados estoy obteniendo, no habrá pérdida de memoria (como en ArrayList con la diferencia entre la capacidad y el número real de elementos), y no habría pérdida de tiempo tratando de duplicar la capacidad.
En cuanto a ArrayList, estoy de acuerdo en que al menos siempre debe usar el constructor con la capacidad inicial, para minimizar la duplicación de las matrices tanto como sea posible.
fuente
ArrayList
yLinkedList
ambos implementosList interface
y sus métodos y resultados son casi idénticos. Sin embargo, existen pocas diferencias entre ellos que hacen que uno sea mejor que otro según el requisito.ArrayList Vs LinkedList
1) la
Search:
ArrayList
operación de búsqueda es bastante rápida en comparación con laLinkedList
operación de búsqueda.get(int index)
enArrayList
da el rendimiento deO(1)
mientras que elLinkedList
rendimiento esO(n)
.Reason:
ArrayList
mantiene un sistema basado en índices para sus elementos, ya que utiliza la estructura de datos de matriz implícitamente, lo que lo hace más rápido para buscar un elemento en la lista. Por otro lado,LinkedList
implementa una lista doblemente vinculada que requiere el recorrido a través de todos los elementos para buscar un elemento.2) la
Deletion:
LinkedList
operación de eliminación proporcionaO(1)
rendimiento mientrasArrayList
proporciona un rendimiento variable:O(n)
en el peor de los casos (al eliminar el primer elemento) yO(1)
en el mejor de los casos (al eliminar el último elemento).Motivo: cada elemento de LinkedList mantiene dos punteros (direcciones) que apuntan a los dos elementos vecinos en la lista. Por lo tanto, la eliminación solo requiere un cambio en la ubicación del puntero en los dos nodos vecinos (elementos) del nodo que se va a eliminar. Mientras que en ArrayList, todos los elementos deben desplazarse para completar el espacio creado por el elemento eliminado.
3) el
Inserts Performance:
LinkedList
método add proporcionaO(1)
rendimiento mientrasArrayList
queO(n)
en el peor de los casos. La razón es la misma que la explicada para eliminar.4)
Memory Overhead:
ArrayList
mantiene índices y datos de elementos mientrasLinkedList
mantiene datos de elementos y dos punteros para nodos vecinosHay algunas similitudes entre estas clases que son las siguientes:
iterator
ylistIterator
devuelto por estas clases sonfail-fast
(si la lista se modifica estructuralmente en cualquier momento después de que se crea el iterador, de cualquier manera, excepto a través de lositerator’s
propios métodos remove o add, el iteradorthrow
aConcurrentModificationException
).¿Cuándo usar LinkedList y cuándo usar ArrayList?
(O(1))
enLinkedList
comparación conArrayList(O(n))
.get method
operaciones de búsqueda ( ) son rápidasArraylist (O(1))
pero no enLinkedList (O(n))
fuente
La operación get (i) en ArrayList es más rápida que LinkedList, porque:
ArrayList: implementación de matriz redimensionable de la interfaz List
LinkedList: implementación de lista doblemente enlazada de las interfaces List y Deque
Las operaciones que se indexan en la lista atravesarán la lista desde el principio o el final, lo que esté más cerca del índice especificado.
fuente
1) Estructura de datos subyacente
La primera diferencia entre ArrayList y LinkedList viene con el hecho de que ArrayList está respaldado por Array, mientras que LinkedList está respaldado por LinkedList. Esto conducirá a más diferencias en el rendimiento.
2) LinkedList implementa Deque
Otra diferencia entre ArrayList y LinkedList es que, aparte de la interfaz List, LinkedList también implementa la interfaz Deque, que proporciona las operaciones de primero en entrar, primero en salir para add () y poll () y varias otras funciones de Deque. 3) Agregar elementos en ArrayList Agregar elemento en ArrayList es una operación O (1) si no activa el redimensionamiento de Array, en cuyo caso se convierte en O (log (n)), por otro lado, agregar un elemento en LinkedList es una operación O (1), ya que no requiere navegación.
4) Eliminar un elemento de una posición
Para eliminar un elemento de un índice particular, por ejemplo, llamando a remove (index), ArrayList realiza una operación de copia que lo acerca a O (n), mientras que LinkedList necesita atravesar ese punto que también lo convierte en O (n / 2) , ya que puede atravesar desde cualquier dirección según la proximidad.
5) Iterando sobre ArrayList o LinkedList
La iteración es la operación O (n) para LinkedList y ArrayList donde n es un número de un elemento.
6) Recuperar elemento de una posición
La operación get (index) es O (1) en ArrayList mientras que su O (n / 2) en LinkedList, ya que necesita recorrer hasta esa entrada. Sin embargo, en la notación Big O, O (n / 2) es solo O (n) porque ignoramos las constantes allí.
7) memoria
LinkedList utiliza un objeto contenedor, Entry, que es una clase anidada estática para almacenar datos y dos nodos, el siguiente y el anterior, mientras que ArrayList solo almacena datos en Array.
Por lo tanto, el requisito de memoria parece menor en el caso de ArrayList que LinkedList, excepto en el caso en que Array realiza la operación de cambio de tamaño cuando copia contenido de un Array a otro.
Si la matriz es lo suficientemente grande, puede tomar mucha memoria en ese punto y desencadenar la recolección de basura, lo que puede ralentizar el tiempo de respuesta.
De todas las diferencias anteriores entre ArrayList vs LinkedList, parece que ArrayList es la mejor opción que LinkedList en casi todos los casos, excepto cuando realiza una operación add () frecuente que remove () o get ().
Es más fácil modificar una lista vinculada que ArrayList, especialmente si está agregando o eliminando elementos desde el inicio o el final porque la lista vinculada internamente mantiene referencias de esas posiciones y son accesibles en tiempo O (1).
En otras palabras, no es necesario recorrer la lista vinculada para llegar a la posición donde desea agregar elementos, en ese caso, la suma se convierte en la operación O (n). Por ejemplo, insertar o eliminar un elemento en el medio de una lista vinculada.
En mi opinión, use ArrayList sobre LinkedList para la mayoría del propósito práctico en Java.
fuente
Una de las pruebas que vi aquí solo realiza la prueba una vez. Pero lo que he notado es que necesita ejecutar estas pruebas muchas veces y eventualmente sus tiempos convergerán. Básicamente, la JVM necesita calentarse. Para mi caso de uso particular, necesitaba agregar / eliminar elementos a una lista que crezca a unos 500 elementos. En mis pruebas
LinkedList
salió más rápido, conLinkedList
alrededor de 50,000 NS yArrayList
llegando a alrededor de 90,000 NS ... más o menos. Ver el código a continuación.fuente
Tanto remove () como insert () tienen una eficiencia de tiempo de ejecución de O (n) para ArrayLists y LinkedLists. Sin embargo, la razón detrás del tiempo de procesamiento lineal proviene de dos razones muy diferentes:
En una ArrayList, llega al elemento en O (1), pero en realidad eliminar o insertar algo lo convierte en O (n) porque todos los siguientes elementos deben cambiarse.
En un LinkedList, se necesita O (n) para llegar realmente al elemento deseado, porque tenemos que comenzar desde el principio hasta llegar al índice deseado. En realidad, eliminar o insertar es constante, ya que solo tenemos que cambiar 1 referencia para eliminar () y 2 referencias para insertar ().
Cuál de los dos es más rápido para insertar y quitar depende de dónde ocurra. Si estamos más cerca del comienzo, LinkedList será más rápido, porque tenemos que pasar por relativamente pocos elementos. Si estamos más cerca del final, una ArrayList será más rápida, porque llegaremos allí en tiempo constante y solo tendremos que cambiar los pocos elementos restantes que la siguen. Cuando se hace precisamente en el medio, LinkedList será más rápido porque pasar por n elementos es más rápido que mover n valores.
Bonificación: Si bien no hay forma de hacer estos dos métodos O (1) para una ArrayList, en realidad hay una manera de hacerlo en LinkedLists. Digamos que queremos revisar la Lista completa eliminando e insertando elementos en nuestro camino. Por lo general, comenzaría desde el principio para cada elemento utilizando LinkedList, también podríamos "guardar" el elemento actual en el que estamos trabajando con un iterador. Con la ayuda de Iterator, obtenemos una eficiencia O (1) para remove () e insert () cuando trabajamos en LinkedList. Lo que lo convierte en el único beneficio de rendimiento. Sé que una LinkedList siempre es mejor que una ArrayList.
fuente
ArrayList extiende AbstractList e implementa la interfaz de lista. ArrayList es una matriz dinámica.
Se puede decir que fue creado básicamente para superar los inconvenientes de las matrices.
La clase LinkedList extiende AbstractSequentialList e implementa la interfaz List, Deque y Queue.
El rendimiento
arraylist.get()
es O (1) mientras quelinkedlist.get()
es O (n)arraylist.add()
es O (1) ylinkedlist.add()
es 0 (1)arraylist.contains()
es O (n) ylinkedlist.contains()
es O (n)arraylist.next()
es O (1) ylinkedlist.next()
es O (1)arraylist.remove()
es O (n) mientras quelinkedlist.remove()
es O (1)En arraylist
iterator.remove()
es O (n)mientras que en lista enlazada
iterator.remove()
es O (1)fuente