Является ли интерфейс List в Java двунаправленным или однонаправленным?

Ответ

Интерфейс java.util.List в Java является однонаправленным (последовательным). Он предоставляет доступ к элементам по индексу и поддерживает итерацию только в прямом направлении (от начала к концу).

Однако конкретные реализации могут иметь внутреннюю двунаправленную структуру:

Реализация Внутренняя структура Доступ по индексу Итерация
ArrayList Массив O(1) Только вперед (однонаправленная)
LinkedList Двусвязный список (узлы с next и prev) O(n) Вперед/назад (четераторы ListIterator)

Ключевой момент: Хотя LinkedList реализован как двусвязный список, через API интерфейса List он ведет себя как однонаправленная последовательность. Для использования двунаправленных возможностей (добавление/удаление с обоих концов) необходимо использовать интерфейс Deque (который реализует LinkedList).

Пример:

List<String> list = new LinkedList<>();
list.add("A"); // Добавление в конец (однонаправленная операция)
list.get(0); // Медленно O(n), т.к. обход с начала

// Двунаправленные операции доступны через Deque
Deque<String> deque = new LinkedList<>();
deque.addFirst("Start"); // Добавление в начало
deque.addLast("End");    // Добавление в конец
String first = deque.pollFirst(); // Удаление из начала

Ответ 18+ 🔞

А, слушай, вот этот ваш java.util.List — он, блядь, как одноколейка, понимаешь? Только вперёд, только хардкор. Даёшь индекс — получаешь элемент, итератор тупо ползёт от начала к концу, и ни хуя больше. Всё, пиздец, обратного хода нет.

Но тут, ёпта, начинается самое интересное! Под капотом-то у реализаций — просто ёперный театр. Смотри:

Реализация Что внутри? Достать по номеру Как бегает?
ArrayList Обычный массив, проще говоря Мгновенно, O(1) Только вперёд, однонаправленная
LinkedList Двусвязный список, сука! (узлы с next и prev) Медленно, O(n) И вперёд, и назад (через ListIterator)

Вот в чём, блядь, парадокс! LinkedList внутри — хитрая жопа, у него каждый элемент знает и соседа спереди, и соседа сзади. Но через рот… то есть через интерфейс List он прикидывается скромнягой и ведёт себя как однонаправленный пацан. Чтобы по-настоящему использовать его двустороннюю мощь, надо, блядь, кастить его до Deque! Вот тогда да — можно и в начало пихать, и с конца выдёргивать, как из кармана.

Смотри, как это выглядит:

// Вот так — обычный лист, однонаправленный, скукота
List<String> list = new LinkedList<>();
list.add("A"); // Кинул в конец — и всё
list.get(0); // Найдет, но будет ползти, как черепаха, O(n)

// А вот так — уже декируем, блядь! Включаем режим бога!
Deque<String> deque = new LinkedList<>();
deque.addFirst("Старт"); // Бахнул в самое начало!
deque.addLast("Конец");  // Или в конец, на выбор
String first = deque.pollFirst(); // Выдрал первый элемент, красота!

Вот так-то, дружок. Интерфейс List — это просто фасад, а под ним может скрываться овердохуища возможностей. Главное — знать, в какую дверь стучаться.