Ответ
Интерфейс 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 — это просто фасад, а под ним может скрываться овердохуища возможностей. Главное — знать, в какую дверь стучаться.