Как заполнить arraylist java с клавиатуры

Обновлено: 17.05.2024

Усвоив, что такое массивы, можно поближе изучить java.util.ArrayList - самый популярный вид списков. По названию пространства имён видно, что данный класс относится к Java.

ArrayList - автоматически расширяемый массив. Вы можете работать с массивом, но при этом не используются квадратные скобки.

Массивы имеют фиксированную длину, и после того как массив создан, он не может расти или уменьшаться. ArrayList может менять свой размер во время исполнения программы, при этом не обязательно указывать размерность при создании объекта. Кроме того, вы без проблем можете вставить новый элемент в середину коллекции. А также спокойно удалить элемент из любого места. Элементы ArrayList могут быть абсолютно любых типов в том числе и null. Это удобно, когда вы не знаете точного размера массива. Для сравнения - гостиница для котов имеет фиксированное число номеров, массив использовать можно. Вы владелец преуспевающей компании и число наёмных работников постоянно увеличивается, обычный массив создавать для учёта сотрудников нецелесообразно. В этом случае удобнее работать со списочным массивом. Иногда говорят, что ArrayList - это массив на стероидах (продвинутый).

Работать с ArrayList просто: создайте нужный объект, вставьте объект методом add(), обращайтесь к нему методом get(), используйте индексирование так же, как для массивов, но без квадратных скобок. ArrayList также содержит метод size(), который возвращает текущее количество элементов в массиве (напомню, что в обычном массиве используется свойство length).

Переменные принято называть во множественном числе.

Рассмотрим на примерах.

Запускаем программу и видим, что в текстовом поле отобразилось имя кота Васьки. Что же произошло? Мы объявили экземпляр класса ArrayList под именем catNames и через метод add() добавили имя. Списочный массив стал содержать одну строку и мы можем в этом убедиться, когда выводим в текстовом поле первый элемент массива через индекс, равный 0.

Продолжим опыт. Перенесём объявление класса на уровень нашего основного класса и добавим через кнопку ещё два имени.

Что теперь произошло? В методе onCreate() как прежде добавляется одно имя, которое выводится в текстовом поле. При нажатии на кнопку мы добавляем ещё два имени, а в текстовой метке выводим имя второго кота через метод catnamesList.get(1).

Хорошо, мы знаем, что добавили трёх котов и поэтому можем обращаться через индекс 0, 1 или 2. А если котов стало слишком много, и мы запутались в их количестве? Тогда нужно вызвать метод size(), который вернёт общее число элементов массива. В этом случае, чтобы получить имя последнего кота в массиве, нужно получить размер массива и отнять единицу.

Вроде бы всё замечательно. Но студия выводит предупреждение у кода метода add(). Почему?

Мы знаем, что у кота есть четыре лапы и хвост. Создадим отдельную переменную для количества лап и попробуем запихнуть их в массив имён. Выглядит как бред, но Java не ругается на наши действия. Вы можете через метод size() убедиться, что размер массива увеличился. Но при попытке вывести последний элемент получим ошибку.

Чтобы вы не совершали подобных ошибок, был придуман следующий подход. Когда вы создаёте новый объект для массива, то в угловых скобках сразу указываете, какой тип собираетесь использовать.

Как только вы исправите пример, то строчка mCatNames.add(paws); будет сразу подчёркнута красной линией. Java поняла, что мы хотим использовать в массиве только строки, а не числа. Поэтому, вы уже не совершите глупых ошибок. Удалите неправильную строку, остальное можно оставить без изменений.

Теперь студия не ругается, и мы можем свернуться калачиком и поспать.

Такая форма записи с угловыми скобками говорит о том, что мы использовали generic-класс (дженерик или обобщение) с типизированными параметрами.

В Java 7 появилась укороченная запись, называемая ромбовидной. Вы можете опустить параметр с правой стороны выражения.

В обобщениях можно использовать только объекты классов. Поэтому запись ArrayList<int> не прокатит. В таких случаях следует использовать класс Integer: ArrayList<Integer>. Но с другой стороны это чревато большим расходом памяти.

Если у вас есть собственный класс, то он используется таким же образом, только с использованием ключевого слова new.

Метод add()

Метод add() самый популярный и не требует особых объяснений. Только не забывайте, что существует перегруженная версия метода, позволяющая вставлять элемент в нужную позицию.

Следует быть осторожным, чтобы ненароком не вставить в несуществующую позицию. По возможности, избегайте операций вставки в середину коллекции. Ведь системе приходится заново пересчитывать индексы элементов.

Методы ensureCapacity() и trimToSize()

Если заранее известно, сколько элементов следует хранить, то перед заполнением массива вызовите метод ensureCapacity():

Первоначальную ёмкость можно задать и в конструкторе в качестве параметра.

Если вы уверены, что списочный массив будет иметь постоянный размер, то можете использовать метод trimToSize(). Это может способствовать рациональному использованию памяти.

Метод indexOf()

Предположим, мы внимательно следим за Рыжиком. Когда он был последним, то его легко было вычислить. Зная размер массива, мы вычитали единицу и получали к нему доступ. Но потом мы стали добавлять в массив других котов и уже не сможем понять, где теперь наш Рыжик. Но выход всегда есть. Существует метод indexOf(), который ищет подходящий элемент и выводит его индекс.

Не забываем, что отсчёт массива идёт с 0, если индекс равен 2, значит он является третим в массиве.

Просмотр всех элементов через цикл

Чтобы вывести всех усатых-полосатых на чистую воду, используем цикл for:

Или укороченная запись:

Метод contains()

Чтобы узнать, есть в массиве какой-либо элемент, можно воспользоваться методом contains(), который вернёт true или false:

Понятно, что в нашем массиве никаких бобиков и барбосов быть не может, поэтому появится надпись false.

Метод remove() - удаление элемента

Для удаления элемента из массива используется метод remove(). Можно удалять по индексу или по объекту:

Элементы, следующие после удалённого элемента, сдвигаются влево, а размер списочного массива уменьшается на единицу.

Метод removeAll() удаляет сразу все элементы. Но лучше использовать метод clear().

Метод removeIf() - удаление элемента по предикату (Java 8)

Раньше, если нужно было удалить элемент из списка по условию, приходилось проходить в цикле по всем элементам и сравнивать их с условием. В Java 8 появился новый метод removeIf(), позволяющий упростить код. Метод использует предикат - вы указываете условие, если оно выполняется, то происходит удаление элемента из списка.

Метод set() - замена элемента

Чтобы заменить элемент в массиве, нужно использовать метод set() с указанием индекса и новым значением. Предположим, вы обнаружили, что у вас не кот Мурзик, а кошка Мурка. Нет проблем.

Метод clear() - очистка массива

Для очистки массива используется метод clear():

Метод работает гораздо быстрее похожего метода removeAll().

Метод toArray() - конвертируем в обычный массив

Также можно сконвертировать из нашего списка в обычный массив и выполнить другие операции. Читайте документацию.

Конвертация в массив может понадобится для ускорения некоторых операций, передачи массива в качестве параметра методам, которые требуют именно массив и другие причины.

Можно было реализовать эту задачу самостоятельно - создать пустой массив, в цикле пройтись по элементам ArrayList и поместить каждый элемент в массив. Важно только проследить за размером массива, который должен совпасть с размером списка.

В Java 8 появился ещё один вариант через Stream.

Сколько раз совпадают элементы

В списочном массиве значения вполне могут совпадать. Например, среди котов попадаются однофамильцы и мы их спокойно можем запихнуть в ArrayList. Но сколько раз повторяются одинаковые элементы?

Интерфейс List

java.util.List является интерфейсом и его можно использовать вместо ArrayList следующим образом:

Или укороченный вариант для Java 7:

Как видите, мы заменили ArrayList на List, но при этом в объявлении оставили new ArrayList(). Всё остальное остаётся без изменений. Кстати, этот способ является рекомендуемым. Но иногда он может не подойти.

Контейнеры List гарантируют определённый порядок следования элементов. Интерфейс List дополняет Collection несколькими методами, обеспечивающими вставку и удаление элементов в середине списка.

Существует две основные разновидности List:

  • Базовый контейнер ArrayList, оптимизированный для произвольного доступа к элементам, но с относительно медленными операциями вставки/удаления элементов в середине списка.
  • Контейнер LinkedList, оптимизированный для последовательного доступа, с быстрыми операциями вставки/удаления в середине списка. Произвольный доступ к элементам LinkedList выполняется относительно медленно, но по широте возможностей превосходит ArrayList.

В отличие от массива контейнер List позволяет добавлять и удалять элементы после создания, а также изменяет свои размеры.

Метод contains() проверяет, присутствует ли объект в списке. Чтобы удалить объект, передайте ссылку на него методу remove(). Кроме того, если у вас имеется ссылка на объект, вы можете определить индекс объекта в List при помощи метода indexOf().

Сам List реализует более общий интерфейс коллекции Collection и можно было даже написать:

Но у Collection нет методов set() и get(), поэтому работать с таким интерфейсом не очень удобно.

Для создания массива можно не только добавлять по одному объекту через метод add(), но и сразу массив через метод Arrays.asList().

Оставим пока в покое котов и создадим массив из объектов Integer.

Но у данного способа есть недостаток. Если вы определили массив таким образом, то уже не можете вставлять или удалять другой элемент (методы add() и delete()), хотя при этом можете изменять существующий элемент.

В Android 11 (R) обещают добавить несколько перегруженных версий метода of(), которые являются частью Java 8.

Заключение

С ArrayList работать проще и удобнее, чем с массивами. Можно без проблем добавлять новые элементы, в том числе и в середину листа. А в случае использования обычного массива вам придётся заново выделять память и перезаписывать элементы, так как размер массива поменять нельзя, после того как была выделена память.

Работа с массивом быстрее и можно использовать массив, если точно знаете заранее размер массива и вам не придётся его динамически менять, делать вставки и т.д.

Структура данных в картинках

Теперь, когда вы получили представление об ArrayList, заглянем за кулисы и посмотрим, как данные хранятся в этом объекте. Источник

Только что созданный объект list содержит свойства elementData и size.

Хранилище значений elementData есть ни что иное как массив определенного типа (указанного в generic), в нашем случае String[]. Если вызывается конструктор без параметров, то по умолчанию будет создан массив из 10-ти элементов типа Object (с приведением к типу, разумеется).

ArrayList

Добавим новый элемент:

ArrayList

Внутри метода add(value) происходят следующие вещи:

1) проверяется, достаточно ли места в массиве для вставки нового элемента;

2) добавляется элемент в конец (согласно значению size) массива.

Если места в массиве не достаточно, новая ёмкость рассчитывается по формуле (oldCapacity * 3) / 2 + 1. Второй момент это копирование элементов. Оно осуществляется с помощью native-метода System.arraycopy(), который написан не на Java.

Ниже продемонстрирован цикл, поочередно добавляющий 15 элементов:

ArrayList

Продолжаем добавлять 2, 3, 4, .

ArrayList

При добавлении 11-го элемента, проверка показывает что места в массиве нет. Соответственно создается новый массив и вызывается System.arraycopy().

ArrayList

После этого добавление элементов продолжается.

ArrayList

Рассмотрим добавление в «середину» списка.

Добавление элемента на позицию с определенным индексом происходит в три этапа:

1) проверяется, достаточно ли места в массиве для вставки нового элемента;

2) подготавливается место для нового элемента с помощью System.arraycopy();


3) перезаписывается значение у элемента с указанным индексом.


Как можно догадаться, в случаях, когда происходит вставка элемента по индексу и при этом в вашем массиве нет свободных мест, то вызов System.arraycopy() случится дважды: первый в ensureCapacity(), второй в самом методе add(index, value), что явно скажется на скорости всей операции добавления.

В случаях, когда в исходный список необходимо добавить другую коллекцию, да еще и в «середину», стоит использовать метод addAll(index, Collection). И хотя, данный метод скорее всего вызовет System.arraycopy() три раза, в итоге это будет гораздо быстрее поэлементного добавления.

Удалять элементы можно двумя способами:

— по индексу remove(index)
— по значению remove(value)

С удалением элемента по индексу всё достаточно просто:

Сначала определяется какое количество элементов надо скопировать:

Затем копируем элементы используя System.arraycopy():

Уменьшаем размер массива и забываем про последний элемент:

При удалении по значению, в цикле просматриваются все элементы списка, до тех пор пока не будет найдено соответствие. Удален будет лишь первый найденный элемент.

При удалении элементов текущая величина capacity не уменьшается, что может привести к своеобразным утечкам памяти. Поэтому не стоит пренебрегать методом trimToSize().

Объединяем два ArrayList

С помощью библиотеки Apache Commons Collections можно объединить два ArrayList.

Сортировка

Сортировать элементы можно при помощи метода Collections.sort().

Интерфейс ListIterator

На практике он мне не встречался. Позволяет проходить по всем элементам вперёд или назад. Для этого он проверяет, есть ли следующий/предыдущий элемент после текущего.

Интерфейс Java List, java.util.List, представляет упорядоченную последовательность объектов. Элементы, содержащиеся в списке Java, вставлять и удалять в соответствии с порядком их появления в списке.

Каждый элемент в списке Java имеет индекс. Первый элемент в имеет индекс 0, второй элемент имеет индекс 1 и т.д.

Вы можете добавить любой объект в список. Если список не типизирован с использованием Java Generics, то вы можете даже смешивать объекты разных типов (классов) в одном и том же списке.

Учебное видео по спискам Java

Если вы предпочитаете смотреть видео вместо чтения текста, вот видео версия этого учебника по Java List:

Java List и Set

Java List и Java Set очень похожи в том, что они оба представляют коллекцию элементов. Тем не менее, есть некоторые существенные различия.

Первое различие между Java List и Java Set состоит в том, что один и тот же элемент может встречаться в списке более одного раза. Это отличается от набора, где каждый элемент может встречаться только один раз.

Реализация List

Будучи подтипом Collection, все методы в интерфейсе Collection также доступны в Listinterface.

  • java.util.ArrayList
  • java.util.LinkedList
  • java.util.Vector
  • java.util.Stack

Также есть параллельные реализации List в пакете java.util.concurrent.

Вот несколько примеров того, как создать экземпляр List:

Как вставить элементы в список Java

Вставить элементы (объекты) в список Java можно методом add (). Вот пример добавления элементов в список Java:

Первые три вызова add () добавляют экземпляр String в конец списка.

Вставить нулевые значения

На самом деле возможно вставить даже нулевые значения в список.

Добавить элементы по определенному индексу

Можно добавить элемент в список по определенному индексу. Интерфейс List имеет версию метода add(), которая принимает индекс в качестве первого параметра, и элемент для вставки в качестве второго параметра. Вот пример вставки элемента с индексом 0.

Если список уже содержит элементы, то теперь они будут перемещаться дальше во внутренней последовательности. Элемент, который имел индекс 0 до того, как новый элемент был вставлен в индекс 0, будет перемещен в индекс 1 и т.д.

Вставляем все элементы из одного списка в другой

Можно добавить все элементы из одного списка в другой. Сделаем это с помощью метода ListaddAll (). Результат представляет собой объединение двух списков.

Этот пример добавляет все элементы из listSource в listDest.

Метод addAll () принимает набор в качестве параметра, поэтому в качестве параметра можно передать список или набор.

Получить элементы из списка Java

Вы можете получить элементы из списка Java, используя индекс элементов. Методом get (int index). Вот пример доступа к элементам списка с использованием индексов элементов:

Также возможно итерировать элементы списка в том порядке, в котором они хранятся внутри.

Как найти элементы в списке Java

Вы можете найти элементы в списке Java, используя один из этих двух методов:

  1. index()
  2. LastIndexOf ()Метод indexOf () находит индекс первого вхождения в списке заданного элемента.

Найти последнее вхождение элемента в списке

Метод lastIndexOf () находит индекс последнего вхождения в списке данного элемента.

Элемент 1 встречается 2 раза. Индекс последнего равен 2.

Проверка: содержит ли список элемент?

Вы можете проверить, содержит ли Java List данный элемент, используя метод List contains ().

Чтобы определить, содержит ли List этот элемент, List будет внутренне выполнять итерации своих элементов и сравнивать каждый элемент с объектом, переданным в качестве параметра.

Поскольку можно добавить нулевые значения в список, фактически можно проверить, содержит ли список нулевое значение.

Очевидно, что если входной параметр для contains () имеет значение null, метод contains () не будет использовать метод equals() для сравнения с каждым элементом, а вместо этого использует оператор ==.

Как удалить элементы из списка Java

Вы можете удалить элементы из списка Java с помощью этих двух методов:

  • remove(Object element)
  • remove(int index)

remove (Object element) удаляет элемент в списке, если он присутствует. Все последующие элементы, затем перемещаются вверх по списку. Таким образом, их индекс уменьшается на 1.

Этот пример сначала добавляет элемент, а затем снова удаляет его.

Метод List remove (int index) удаляет элемент по указанному индексу.

После выполнения этого примера кода список будет содержать элементы 1 и 2 с индексами 0 и 1.

Очистить список

Интерфейс Java List содержит метод clear (), который удаляет все элементы из списка при вызове. Удаление всех элементов также называется очисткой.

Как сохранить все элементы из одного списка в другом

Метод retainAll () способен сохранять все элементы из одного списка в другом. Другими словами, метод retain () удаляет все элементы, которые не найдены в другом списке.

Результатом является пересечение двух списков.

Узнать количество элементов

Вы можете получить количество элементов вызвав метод size (). Вот пример:

Подсписок списка

Метод subList () может создавать новый List с подмножеством элементов из исходного List.

Конечный индекс является последним индексом подсписка, но элемент в последнем индексе не включается в подсписок. Это похоже на то, как работает метод подстроки Java String.

После выполнения list.subList (1,3) подсписок будет содержать элементы с индексами 1 и 2.

Помните, что исходный список содержит 4 элемента с индексами от 0 до 3. Вызов list.subList (1,3) будет включить индекс 1, но исключить индекс 3, сохраняя тем самым элементы с индексами 1 и 2.

Преобразовать list в set

Вы можете преобразовать список Java в набор(set), создав новый набор и добавив в него все элементы из списка. Набор удалит все дубликаты.

Таким образом, результирующий набор будет содержать все элементы списка, но только один раз.

Обратите внимание, что список содержит элемент String 3 два раза. Набор будет содержать эту строку только один раз. Таким образом, результирующий набор будет содержать строки: element 1 , element 2 and element 3 .

Общие списки

По умолчанию вы можете поместить любой объект в список, но Java позволяет ограничить типы объектов, которые вы можете вставить в список.

Этот список теперь может содержать только экземпляры MyObject. Затем вы можете получить доступ к итерации его элементов без их приведения.

Сортировка

Вы можете отсортировать список с помощью метода Collections sort ().

Класс Java String реализует интерфейс Comparable, вы можете отсортировать их в естественном порядке, используя метод Collections sort ().

Сортировка списка с помощью Comparatorimplementation

Вот код сортировки:

Обратите внимание на реализацию Comparator в приведенном выше примере. Эта реализация сравнивает только поле марки автомобилей Car. Можно создать другую реализацию Comparator, которая сравнивает номерные знаки или даже количество дверей в автомобилях.

Возможно реализовать Comparator с использованием Java Lambda. Вот пример, который сортирует объекты List of Car с использованием трех различных реализаций интерфейса Comparator, каждая из которых сравнивает экземпляры Car по своему полю:

Итерации

Вы можете выполнить итерацию списка несколькими различными способами. Три наиболее распространенных способа:

  • Использование итератора
  • Использование цикла for-each
  • Использование цикла for
  • Использование API Java Stream

Итерация списка с помощью итератора

Вызывая метод iterator () интерфейса List.

Вызов hasNext () выполняется внутри цикла while.

Внутри цикла while вы вызываете метод Iterator next () для получения следующего элемента, на который указывает Iterator.

Если список задан с использованием Java Generics, вы можете сохранить некоторые объекты внутри цикла while.

Итерация списка с использованием цикла For-Each

Цикл for выполняется один раз для каждого элемента. Внутри цикла for каждый элемент, в свою очередь, связан с переменной obj.

Можно изменить тип переменной внутри цикла for.

Итерация списка с помощью цикла For

Цикл for создает переменную int и инициализирует ее 0. Затем она зацикливается, пока переменная int i меньше размера списка. Для каждой итерации переменная i увеличивается.

Внутри цикла for обращаемся к элементам List с помощью метода get (), передавая в качестве параметра переменную i.

Опять же, если список напечатан с использованием Java Generics, например, для для строки, то вы можете использовать универсальный тип списка в качестве типа для локальной переменной, которая присваивается каждому элементу списка во время итерации.

Тип локальной переменной внутри цикла for теперь String. Поскольку список обычно типизируется как String, он может содержать только объекты String.

Следовательно, компилятор знает, что только метод String может быть возвращен из метода get (). Поэтому вам не нужно приводить элемент, возвращенный get (), в String.

Перебор списка с использованием API Java Stream

Четвертый способ итерации через API Java Stream. Для итерации вы должны сначала получить поток из списка. Получение потока из списка в Java выполняется путем вызова метода Liststream ().

Как только вы получили поток из списка, вы можете выполнить итерацию потока, вызвав его метод forEach ().

Вызов метода forEach () заставит Stream выполнить внутреннюю итерацию всех элементов потока.

Средняя оценка / 5. Количество голосов:

Спасибо, помогите другим - напишите комментарий, добавьте информации к статье.

В Java массивы имеют фиксированную длину и не могут быть увеличены или уменьшены. Класс ArrayList реализует интерфейс List и может менять свой размер во время исполнения программы, при этом не обязательно указывать размерность при создании объекта. Элементы ArrayList могут быть абсолютно любых типов в том числе и null.

Пример создания объекта ArrayList

Можно инициализировать массив на этапе определения. Созданный объект list содержит свойство size. Обращение к элементам массива осуществляется с помощью метода get(). Пример :

Добавление элемента в массив ArrayList, метод add

Работать с ArrayList просто: необходимо создать объект и вставлять созданные объекты методом add(). Обращение к элементам массива осуществляется с помощью метода get(). Пример:

Замена элемента массива ArrayList, метод set

Чтобы заменить элемент в массиве, нужно использовать метод set() с указанием индекса и новым значением.

Удаление элемента массива ArrayList, метод remove

Для удаления элемента из массива используется метод remove(). Можно удалять по индексу или по объекту:

ПРИМЕЧАНИЕ: элементы, следующие после удалённого элемента, перемещаются на одну позицию ближе к началу. То же самое относится и к операции вставки элемента в середину списка.

Для очистки всего массива используется метод clear():

Определение позиции элемента ArrayList, метод indexOf

В списочном массиве ArrayList существует метод indexOf(), который ищет нужный элемент и возвращает его индекс.

Отсчёт в массиве начинается с 0, если индекс равен 2, значит он является третьим в массиве.

Проверка наличие элемента в ArrayList, метод contains

Чтобы узнать, есть в массиве какой-либо элемент, можно воспользоваться методом contains(), который вернёт логическое значение true или false в зависимости от присутствия элемента в наборе :

Понятно, что в массиве никаких овощей быть не может, поэтому в консоле будет отображено false.

Создание массива из элементов ArrayList, метод toArray

Для конвертирования набора элементов в обычный массив необходимо использовать метод toArray().

Интерфейс List

java.util.List является интерфейсом и его следует использовать вместо ArrayList следующим образом :

Или укороченный вариант для Java 7:

В примере тип ArrayList заменен на List, но в объявлении оставлен new ArrayList(). Всё остальное остаётся без изменений. Это является рекомендуемым способом.

Интерфейс List реализует более общий интерфейс коллекции Collection.

Преобразование массива в список, Arrays

Для создания массива можно не только добавлять по одному объекту через метод add(), но и сразу массив с использованием Arrays.asList(. ).

Пример создания и инициализации массива из объектов Integer.

У данного способа есть недостаток. Если вы определили списочный массив таким образом, то уже не можете вставлять или удалять элемент, хотя при этом можете изменять существующий элемент.

Взбрело мне в голову написать несколько статей, о том как реализованы некоторые структуры данных в Java. Надеюсь, статьи будут полезны визуалам (картинки наше всё), начинающим java-визуалам а также тем кто уже умеет писать new ArrayList(), но слабо представляет что же происходит внутри.


Сегодня поговорим о ArrayList-ах

ArrayList — реализует интерфейс List. Как известно, в Java массивы имеют фиксированную длину, и после того как массив создан, он не может расти или уменьшаться. ArrayList может менять свой размер во время исполнения программы, при этом не обязательно указывать размерность при создании объекта. Элементы ArrayList могут быть абсолютно любых типов в том числе и null.

Создание объекта

Только что созданный объект list, содержит свойства elementData и size.

Хранилище значений elementData есть ни что иное как массив определенного типа (указанного в generic), в нашем случае String[]. Если вызывается конструктор без параметров, то по умолчанию будет создан массив из 10-ти элементов типа Object (с приведением к типу, разумеется).





Вы можете использовать конструктор ArrayList(capacity) и указать свою начальную емкость списка.

Добавление элементов



Внутри метода add(value) происходят следующие вещи:

1) проверяется, достаточно ли места в массиве для вставки нового элемента;


2) добавляется элемент в конец (согласно значению size) массива.


Весь метод ensureCapacity(minCapacity) рассматривать не будем, остановимся только на паре интересных мест. Если места в массиве не достаточно, новая емкость рассчитывается по формуле (oldCapacity * 3) / 2 + 1. Второй момент это копирование элементов. Оно осуществляется с помощью native метода System.arraycopy(), который написан не на Java.

Ниже продемонстрирован цикл, поочередно добавляющий 15 элементов:





При добавлении 11-го элемента, проверка показывает что места в массиве нет. Соответственно создается новый массив и вызывается System.arraycopy().




После этого добавление элементов продолжается




Добавление в «середину» списка

Добавление элемента на позицию с определенным индексом происходит в три этапа:

1) проверяется, достаточно ли места в массиве для вставки нового элемента;


2) подготавливается место для нового элемента с помощью System.arraycopy();





3) перезаписывается значение у элемента с указанным индексом.




Как можно догадаться, в случаях, когда происходит вставка элемента по индексу и при этом в вашем массиве нет свободных мест, то вызов System.arraycopy() случится дважды: первый в ensureCapacity(), второй в самом методе add(index, value), что явно скажется на скорости всей операции добавления.

В случаях, когда в исходный список необходимо добавить другую коллекцию, да еще и в «середину», стоит использовать метод addAll(index, Collection). И хотя, данный метод скорее всего вызовет System.arraycopy() три раза, в итоге это будет гораздо быстрее поэлементного добавления.

Удаление элементов

Удалять элементы можно двумя способами:
— по индексу remove(index)
— по значению remove(value)

С удалением элемента по индексу всё достаточно просто


Сначала определяется какое количество элементов надо скопировать


затем копируем элементы используя System.arraycopy()


уменьшаем размер массива и забываем про последний элемент

При удалении по значению, в цикле просматриваются все элементы списка, до тех пор пока не будет найдено соответствие. Удален будет лишь первый найденный элемент.

Дополнение 1: Как верно заметил MikeMirzayanov, при удалении элементов текущая величина capacity не уменьшается, что может привести к своеобразным утечкам памяти. Поэтому не стоит пренебрегать методом trimToSize().

Итоги

— Быстрый доступ к элементам по индексу за время O(1);
— Доступ к элементам по значению за линейное время O(n);
— Медленный, когда вставляются и удаляются элементы из «середины» списка;
— Позволяет хранить любые значения в том числе и null;
— Не синхронизирован.

Ссылки


Пишите в комментариях пожелания/замечания и есть ли смысл продолжать.

Читайте также: