Al leer la documentación de Java para la lista ADT , dice:
La interfaz de Lista proporciona cuatro métodos para el acceso posicional (indexado) a los elementos de la lista. Las listas (como las matrices Java) están basadas en cero. Tenga en cuenta que estas operaciones pueden ejecutarse en un tiempo proporcional al valor del índice para algunas implementaciones (la clase LinkedList, por ejemplo). Por lo tanto, iterar sobre los elementos en una lista generalmente es preferible a indexarlo si la persona que llama no conoce la implementación.
¿Qué significa esto exactamente? No entiendo la conclusión que se extrae.
Respuestas:
En una lista vinculada, cada elemento tiene un puntero al siguiente elemento:
Para acceder
item3
, puede ver claramente que necesita caminar desde la cabeza a través de cada nodo hasta llegar al elemento 3, ya que no puede saltar directamente.Por lo tanto, si quisiera imprimir el valor de cada elemento, si escribo esto:
lo que pasa es esto:
Esto es terriblemente ineficiente porque cada vez que está indexando se reinicia desde el principio de la lista y revisa cada elemento. ¡Esto significa que su complejidad es efectivamente
O(N^2)
solo para recorrer la lista!Si en cambio hice esto:
entonces lo que pasa es esto:
todo en un solo recorrido, que es
O(N)
.Ahora, ir a la otra puesta en práctica de
List
la cual estáArrayList
, que uno está respaldado por una simple matriz. En ese caso, los dos recorridos anteriores son equivalentes, ya que una matriz es contigua, por lo que permite saltos aleatorios a posiciones arbitrarias.fuente
REVERSE_THRESHOLD
está configurado en 18java.util.Collections
, es extraño ver una respuesta tan votada sin el comentario.List l = unknownList(); if (l instanceof RandomAccess) /* do indexed loop */ else /* use iterator/foreach */
La respuesta está implícita aquí:
Una lista vinculada no tiene un índice inherente; la llamada
.get(x)
requerirá la implementación de la lista para encontrar la primera entrada y llamar.next()
x-1 veces (para un O (n) o acceso de tiempo lineal), donde una lista respaldada por una matriz puede indexarsebackingarray[x]
en O (1) o tiempo constante.Si miras el JavaDoc
LinkedList
, verás el comentariomientras que JavaDoc para
ArrayList
tiene el correspondienteUna pregunta relacionada titulada "Big-O Summary for Java Collections Framework" tiene una respuesta que apunta a este recurso, "Java Collections JDK6", que puede resultarle útil.
fuente
Si bien la respuesta aceptada es ciertamente correcta, podría señalar un pequeño defecto. Citando a Tudor:
Esto no es del todo cierto. La verdad es esa
fuente: Designing for Performance, documento de Android de Google
Tenga en cuenta que el bucle escrito a mano se refiere a la iteración indexada. Sospecho que es por el iterador que se usa con bucles mejorados. Produce un rendimiento menor en penalización en una estructura respaldada por una matriz contigua. También sospecho que esto podría ser cierto para la clase Vector.
Mi regla es, use el bucle for mejorado siempre que sea posible, y si realmente le importa el rendimiento, use la iteración indexada solo para ArrayLists o Vectors. En la mayoría de los casos, incluso puede ignorar esto: el compilador podría estar optimizando esto en segundo plano.
Simplemente quiero señalar que, en el contexto del desarrollo en Android, ambos recorridos de ArrayLists no son necesariamente equivalentes . Solo comida para pensar.
fuente
Iterar sobre una lista con un desplazamiento para la búsqueda, como
i
, es análogo al algoritmo del pintor Shlemiel .Fuente .
Esta pequeña historia puede facilitar la comprensión de lo que está sucediendo internamente y por qué es tan ineficiente.
fuente
Para encontrar el elemento i-th de a,
LinkedList
la implementación pasa por todos los elementos hasta el i-th.Entonces
fuente