В чем разница между List и LinkedList в Dart?

Ответ

В Dart основными структурами данных являются List (аналог ArrayList) и LinkedList из dart:collection, которые имеют принципиальные различия в реализации и производительности.

List (как ArrayList):

  • Основан на динамическом массиве
  • Быстрый доступ по индексу: O(1)
  • Вставка/удаление в середине требует сдвига элементов: O(n)
  • Оптимален для частого чтения и итерации

LinkedList:

  • Основан на двусвязном списке элементов, наследующих LinkedListEntry
  • Доступ по индексу медленный: O(n) — требует перебора
  • Вставка/удаление при известной позиции: O(1)
  • Оптимален для частых изменений структуры

Примеры использования:

// List (используется в 99% случаев)
void listExample() {
  final list = [1, 2, 3, 4, 5];

  // Быстрый доступ
  print(list[2]); // 3 - O(1)

  // Медленная вставка в середину
  list.insert(2, 10); // O(n) - сдвигает элементы

  // Быстрая итерация
  for (var item in list) {
    print(item);
  }
}

// LinkedList (специальные случаи)
import 'dart:collection';

class Task extends LinkedListEntry<Task> {
  final String name;
  Task(this.name);
}

void linkedListExample() {
  final taskList = LinkedList<Task>();
  final task1 = Task('Design');
  final task2 = Task('Develop');
  final task3 = Task('Test');

  taskList.add(task1);
  taskList.add(task2);

  // Быстрая вставка после task1
  task1.insertAfter(task3); // O(1)

  // Быстрое удаление
  task2.unlink(); // O(1)

  // Медленный поиск по значению
  final found = taskList.firstWhere(
    (task) => task.name == 'Test',
    orElse: () => null,
  );
}

Когда что использовать:

  • List: большинство случаев — хранение данных, отображение в ListView, работа с JSON
  • LinkedList: реализации LRU-кэша, undo/redo систем, когда нужны частые вставки/удаления в середине последовательности

Ответ 18+ 🔞

Блин, ну вот смотри, как в жизни бывает. Есть у тебя два инструмента — List и LinkedList. И они, блядь, как молоток и скальпель: для гвоздей один, для мозговой хирургии — другой. Если перепутаешь — будет вам хиросима и нигерсраки, в смысле, полный пиздец в коде.

List — это как твой старый добрый чемодан (ну, или ArrayList, если ты из Java).

Всё просто, ёпта. Взял, накидал вещей — работает. Хочешь достать носки из середины? Один движ — и вот они. Это потому что внутри у него массив, всё по полочкам лежит.

  • Доступ по индексу (list[2]) — это просто праздник какой-то, O(1). Мгновенно.
  • А вот впихнуть или выковырять что-то из середины — вот тут начинается движуха. Надо всё, что после, сдвинуть. O(n), детка. Если список овердохуища большой, то это уже не шутки.
void listExample() {
  final list = [1, 2, 3, 4, 5];
  print(list[2]); // 3 - берёшь и берёшь, как будто так и надо
  list.insert(2, 10); // А вот тут уже придётся поработать лопатой, сдвигать элементы
}

LinkedList — это уже хитрая жопа.

Представь цепочку, где каждый элемент знает только своего соседа слева и справа. Индексов тут нет, ёклмн. Хочешь найти пятый элемент? Пиздец, начинай с первого и шагай, пока не дойдёшь. Зато если ты УЖЕ стоишь на каком-то элементе и хочешь вставить новый прямо перед ним или после — красота! Проще пареной репы: поменял пару ссылочек у соседей и всё, O(1). Ничего сдвигать не надо.

import 'dart:collection';

class Task extends LinkedListEntry<Task> {
  final String name;
  Task(this.name);
}

void linkedListExample() {
  final taskList = LinkedList<Task>();
  final task1 = Task('Design');
  final task2 = Task('Develop');
  final task3 = Task('Test');

  taskList.add(task1);
  taskList.add(task2);
  task1.insertAfter(task3); // Вот это да! Вставил за дизайном разработку за милую душу, быстро.
  task2.unlink(); // И удалил тоже моментально, чик — и нет его.
}

Так когда же что брать? Давай без соплей.

  • List — это твой рабочий конь. В 99% случаев бери его. Данные из API пришли? List. В ListView засунуть? List. JSON распарсить? List, ёбать копать! Он для чтения и итерации — просто пизда рулю.
  • LinkedList — это спецназ для особых операций. Нужно часто тасовать элементы внутри огромной цепочки, вставлять-удалять, а искать по индексу не надо? Например, свой кэш пишешь или историю команд (undo/redo). Вот тогда — да, это твой вариант. Но честно? В обычной жизни он нужен реже, чем зубочистка на битве с драконом.

Короче, правило простое: не выёбывайся. Начинай всегда с List. А если потом упрёшься в то, что он тебя тормозит на конкретных вставках — вот тогда уже иди гугли LinkedList и думай, стоит ли овчинка выделки. Чаще всего — не стоит.

Видео-ответы