java-listas-arraylist-vs-linkedlist

Listas en Java: ArrayList y LinkedList

  • 4 min

Una List es una colección ordenada que admite duplicados y acceso por posición.

Queremos guardar datos ordenados y acceder a ellos por su posición.

Pero al ir a escribir el código, el IDE nos ofrece dos opciones principales:

  1. List<String> lista = new ArrayList<>();
  2. List<String> lista = new LinkedList<>();

Ambas funcionan igual desde fuera (tienen los mismos métodos add, get, remove). Pero por dentro son mundos completamente distintos. Elegir mal puede hacer que tu aplicación vuele o que se arrastre.

Hoy vamos a ver qué ocurre bajo el capó.

ArrayList

El ArrayList es la implementación por defecto y la que usarás el 90% del tiempo.

¿Cómo funciona por dentro?

Internamente, un ArrayList ES un array normal (Object[]). Cuando su array interno se llena, ArrayList:

  1. Crea un nuevo array más grande (normalmente un 50% más grande).
  2. Copia todos los elementos del viejo al nuevo.
  3. Borra el viejo.
  • Acceso Ultra-Rápido (O(1)): Como es un array, si pides get(5000), Java sabe calcular la dirección de memoria exacta instantáneamente. No tiene que contar.
  • Eficiencia de Caché: Al estar los datos juntos en memoria (contiguos), al procesador le encanta recorrerlos.
  • Insertar/Borrar en medio es lento (O(n)): Si tienes un array de 1.000 elementos e insertas algo en la posición 0, Java tiene que desplazar los 1.000 elementos un paso a la derecha para hacer hueco.

LinkedList

La LinkedList funciona con Nodos. Cada elemento es un objeto que guarda el dato y dos “punteros”: uno al siguiente elemento y otro al anterior (Lista Doblemente Enlazada).

Los datos NO están juntos en memoria. Están esparcidos por el Heap, unidos solo por referencias.

  • Inserción/Borrado rápido (O(1)): Si quieres meter a alguien en medio de una fila de personas dadas de la mano, solo tienes que soltar dos manos y agarrar al nuevo. No hay que mover a nadie más.
  • Acceso Lento (O(n)): Si pides get(5000), Java tiene que empezar desde el primero y saltar de nodo en nodo 5.000 veces (“tú conoces al siguiente, y tú al siguiente…”). No hay atajos.
  • Gasta más memoria: Cada dato necesita crear un objeto extra (Nodo) y guardar dos referencias (Next/Prev).

Comparativa de complejidad (Big O)

OperaciónArrayListLinkedListGanador
get(index)O(1) (Inmediato)O(n) (Lento)🏆 ArrayList
add(final)O(1) (Muy rápido*)O(1) (Rápido)Empate
add(inicio)O(n) (Desplaza todo)O(1) (Solo punteros)🏆 LinkedList
remove(index)O(n) (Desplaza elementos)O(n) (Primero localiza el nodo)Depende del patrón de acceso
MemoriaBaja (Compacta)Alta (Nodos extra)🏆 ArrayList

*El add de ArrayList es rápido amortizado, salvo cuando le toca redimensionar el array. El remove de LinkedList es O(1) solo si el iterador ya está situado en el nodo. Si recibe un índice, primero tiene que recorrer la lista.

¿Cuál uso?

Como criterio inicial:

Usa ArrayList como opción por defecto.

Código de ejemplo

El uso es idéntico gracias al Polimorfismo.

import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;

public class BatallaListas {
    public static void main(String[] args) {

        // RECOMENDADO: Usar la interfaz 'List' a la izquierda
        List<String> nombres = new ArrayList<>();

        nombres.add("Ana");
        nombres.add("Carlos");
        nombres.add(1, "Beatriz"); // Inserta en medio (ArrayList sufre aquí)

        System.out.println(nombres.get(1)); // Acceso directo (ArrayList vuela aquí)

        // Si quisiéramos cambiar a LinkedList, solo cambiamos el 'new':
        // List<String> nombres = new LinkedList<>();
        // El resto del código NO cambia.
    }
}
Copied!

Conversión entre arrays y listas

A veces tienes un Array viejo y quieres convertirlo a una Lista moderna (o viceversa).

  1. Array -> Lista: Arrays.asList() crea una lista de tamaño fijo. Si quieres modificarla, envuélvela en un ArrayList.
String[] arr = {"A", "B", "C"};
List<String> lista = new ArrayList<>(Arrays.asList(arr));
Copied!
  1. Lista -> Array:
String[] resultado = lista.toArray(new String[0]);
Copied!