Ответ
Метод get() присутствует в ArrayList благодаря реализации интерфейса List<E>, который объявляет этот метод как обязательный для доступа к элементам по индексу.
Иерархия интерфейсов:
Iterable<E> (итерация)
↓
Collection<E> (базовые операции коллекции)
↓
List<E> (упорядоченная коллекция с доступом по индексу)
↓
ArrayList<E> (реализация на основе массива)
Реализация в ArrayList:
public E get(int index) {
// Проверка выхода за границы (с Java 9)
Objects.checkIndex(index, size);
// Прямой доступ к элементу массива - O(1)
return elementData[index];
}
Ключевые особенности:
- Сложность O(1) - доступ к элементу происходит за константное время, так как используется обычный массив
- Проверка границ - метод проверяет, что индекс находится в диапазоне [0, size-1]
- Type safety - благодаря дженерикам, возвращаемый тип соответствует типу коллекции
Пример использования:
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
String element = list.get(1); // "B" - получение за O(1)
// Сравнение с LinkedList (реализация get() через итерацию)
List<String> linkedList = new LinkedList<>(list);
String linkedElement = linkedList.get(1); // O(n) - требует обхода
Важно: Метод get() выбрасывает IndexOutOfBoundsException, если индекс выходит за пределы списка.
Ответ 18+ 🔞
А, слушай, вот эта вся история с get() в ArrayList — это вообще отдельный цирк с конями, если разобраться. Ну типа, смотри, блядь: вроде бы обычный метод, доступ по индексу, чего уж проще. Но нет, ёпта, тут под капотом целая опера разворачивается!
Так вот, этот самый get() у ArrayList появляется не потому, что он такой умный сам по себе, а потому что он, сука, обязан его реализовать! А обязан он потому, что подписал контракт — интерфейс List<E>. Это как если бы ты пошёл в армию, блядь: там тебе говорят «надо», и ты, хочешь не хочешь, делаешь. Вот и ArrayList — он делает.
Вся эта иерархия выглядит примерно так, представь:
Iterable<E> (может просто по себе пройтись, как бомж по помойке)
↓
Collection<E> (уже может кучу базового дерьма делать — добавить, удалить)
↓
List<E> (а вот тут уже конкретика: «дай мне элемент по номеру, сука!»)
↓
ArrayList<E> (и вот он, наш герой, который это всё реализует на массиве)
А внутри ArrayList этот метод get() — это просто праздник какой-то, блядь:
public E get(int index) {
// Сначала, как порядочный гражданин, проверяет, не вышел ли ты за рамки дозволенного
Objects.checkIndex(index, size);
// А потом — бац! — и достаёт из своего внутреннего массива элемент за O(1)
return elementData[index];
}
И вот в чём, блядь, соль, понимаешь:
- Скорость — огонь! O(1), потому что под капотом обычный массив. Тыкнул пальцем — получил. Никаких тебе обходов, никаких итераций, чистая математика, адресная арифметика, ёба!
- Проверяет границы. Не даст тебе, распиздяю, ткнуть в -1 или в размер+1. Скажет тебе «нет, дружок, иди нахуй» через
IndexOutOfBoundsException. - Типизация. Благодаря дженерикам, он тебе вернёт именно
String, а не какую-нибудь хуйню в видеObject, которую потом надо кастовать.
Ну и чтобы совсем понятно было, смотри пример:
// Создаём наш быстрый ArrayList
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
String element = list.get(1); // Вытащил "B" моментально, как фокусник из рукава!
// А вот для сравнения — LinkedList, блядь
List<String> linkedList = new LinkedList<>(list);
String linkedElement = linkedList.get(1); // А вот тут уже O(n) — он будет ползти от начала списка, как черепаха, ебать её в сраку!
И главное, запомни, как отче наш: если попробуешь вызвать get(999) на списке из трёх элементов, получишь не элемент, а пиздюлину в виде исключения. Так что с индексами, дружище, аккуратнее, а то мало не покажется!