Что такое ArrayList в Java
Вы уже умеете создавать массивы в Java? Тогда самое время узнать что такое Arraylist. Ну что ж, поехали!
Допустим, Вы работаете программистом на компанию, которая осуществляет доставку товаров по всему миру. И Вам необходимо сохранить список городов, в которые осуществляется доставка.
Вы это можете сделать 2 способами:
1. С помощью обычного массива
2. С помощью Arraylist
Давайте рассмотрим каждый из этих способов. И тогда сразу станет понятно почему Arraylist — это лучший друг Java программиста.
1. С ПОМОЩЬЮ ОБЫЧНОГО МАССИВА
Создаем обычный массив с именем deliveryCities. В фигурных скобках прописываем значения элементов массива, то есть названия городов. Например:
String [ ] deliveryCities = < "Chicago" , "New York" , "Toronto" , "Paris" >
В результате, будет создан массив deliveryCities на 4 элемента. И если мы заходим получить 3-й элемент массива – мы напишем deliveryCities[2], поскольку 3-й элемент имеет индекс 2. Таким образом мы можем создать массив из элементов любого типа, после чего можем работать с этими элементами.
Но что, если мы хотим добавить еще один город для доставки, например, London?
«Та чего ж тут сложного?» — скажите Вы мне. «Просто берешь и увеличиваешь массив с 4 до 5 элементов.»
И вот Вам мой ответ: «Так сделать не получится! Потому что в Java нет возможности изменять длину массивов. А это значит, что если Вы изначально создали массив на 4 элемента, значит уже этот массив будет всегда на 4 элемента.»
Так как же быть. Можно попробовать исхитриться и сделать следующее. Мы можем создать еще один массив, только уже не на 4, а на 5 элементов. Далее скопировать в этот массив 4 элемента из предыдущего массива плюс добавить еще один город — London.
Решение будет выглядеть так:
String [ ] deliveryCities = < "Chicago" , "New York" , "Toronto" , "Paris" >;
String [ ] deliveryCities2 = new String [ deliveryCities . length + 1 ] ;
for ( int i = 0 ; i < deliveryCities . length ; i ++ ) <
deliveryCities2 [ i ] = deliveryCities [ i ] ;
deliveryCities2 [ deliveryCities . length ] = "London" ;
Таким образом мы сначала создали новый массив deliveryCities2 на единицу большей длины, чем первый массив, дальше поэлементно скопировали первый массив во второй и только потом последним элементом второго массива установили город London. Согласитесь, достаточно неудобно. К тому же нам пришлось создавать второй массив, чтобы вставить всего лишь 1 элемент. А как тогда быть? Есть ли более элегантное решение данной проблемы? Есть, и оно называется ArrayList .
2. С ПОМОЩЬЮ ARRAYLIST
Так что же такое Arraylist? Говоря простым и понятным языком, ArrayList – это список, который очень похож на массив за исключением того, что он имеет произвольную длину и целый ряд методов, которые позволяют добавлять, удалять, заменять элементы списка в любое время и в любом месте.
А это значит, что Вы можете, например, сначала создать Arraylist на 4 элемента, а потом взять и добавить еще 7 элементов, а потом удалить 2 элемента, а потом снова добавить 15 элементов и т.д. Вы поняли идею, Arraylist, как резиновый, его можно увеличивать или уменьшать безо всяких проблем.
Также, как Вы помните, в статье по переменным, мы обсуждали, что всего есть 8 примитивных типов в Java. Так вот ArrayList к ним не относится. Arraylist — это так называемый объектный тип, который входит в Java Core, а именно java.util.ArrayList.
Работать с ArrayList очень и очень просто
Во-первых, как и в случае с массивами, нужно создать список. Создать список можно несколькими способами. Наиболее распространенным способом является следующая структура:
Для нашего примера с городами:
ArrayList
ArrayList — это структура данных в языке Java, предназначенная для хранения множества значений. Это усовершенствованный массив, в котором можно изменять количество элементов и с легкостью выполнять с ними различные операции.
Освойте профессию «Java-разработчик»
Такие структуры данных в целом называют динамическими массивами. Обычный массив — это линейный набор элементов с фиксированной длиной, в котором можно хранить данные, как правило, одного типа. Например, может существовать массив чисел, строк и так далее. А динамический массив фиксированной длины не имеет. Его длина динамически изменяется, отсюда и название.
Что такое ArrayList
ArrayList — это в первую очередь упорядоченный набор данных: слово «упорядоченный» означает, что у каждого элемента в наборе есть свое месторасположение. Оно описывается индексом — числом, хранящим положение элемента. Индексы начинаются с нуля. Первый элемент в массиве будет иметь индекс 0, второй — 1, и так далее.
Идея ArrayList — расширяемость. Когда разработчик увеличивает количество элементов, длина массива автоматически увеличивается, чтобы уместить их все. Когда какой-то элемент удаляют, длина уменьшается — так структура становится понятнее, без пустых участков. Можно также создать ArrayList с заданной изначальной емкостью, но она автоматически расширится, если элементов станет больше. Кроме того, в ArrayList можно делать много операций, которые неприменимы к обычному массиву. Например, удалять элементы в простом массиве нельзя — только обнулять или перезаписывать. В остальном структура похожа на обычный массив. И вот почему.
Профессия / 14 месяцев
Java-разработчик
Освойте востребованный язык
Для чего нужен ArrayList
Задача любого массива, в том числе динамического, — хранить структурированную и упорядоченную информацию, какой-то набор элементов, для которых важно расположение. А применить его можно огромным количеством способов: для хранения и использования данных, реализации программных структур и алгоритмов, математических или физических операций и многого другого.
Еще одна задача ArrayList — упростить работу с массивами благодаря обилию специальных методов, о которых мы поговорим ниже.
Как устроен ArrayList
Внутри структуры данных — массив фиксированного размера, который удаляется и создается заново с новой длиной, когда внутри ArrayList меняется количество объектов. Технически это выглядит так:
- разработчик отдает команду записать новый элемент;
- внутри ArrayList создается копия текущего массива, который там хранится, но с большей длиной;
- в нужное место расширенной копии добавляется новый элемент;
- старый массив удаляется.
Чтобы оптимизировать этот процесс, новая длина по умолчанию в полтора раза больше старой — так массив не приходится «переписывать» слишком часто.
Станьте Java-разработчиком
и создавайте сложные сервисы
на востребованном языке
Особенности ArrayList
В интерфейсе List описано множество методов, с помощью которых можно легко управлять динамическим массивом: добавлять элементы в конец или в начало, вставлять их в любое место структуры, быстро получать данные, видоизменять весь массив разом, «сливать» несколько коллекций друг с другом и делать многое другое. Для этого не нужно создавать сложные алгоритмы или добавлять вспомогательные структуры — достаточно написать одну строчку кода.
Еще одна особенность ArrayList — технически он хранит только ссылочные типы. Это значит, что фактически внутри него лежат ссылки на сложные элементы. Но внутри такого массива можно хранить и «простые», примитивные элементы вроде числа или строки — для них автоматически создастся специальная «обертка». Так что фактически массив можно использовать для хранения любых типов данных.
Как работать с ArrayList
При создании ArrayList можно сделать пустым с помощью команды
ArrayList имя переменной = new ArrayList();
Также можно указать в скобках существующую коллекцию, и тогда динамический массив создастся на ее основе и будет содержать в себе ее элементы.
Еще можно задать массиву изначальную емкость — capacity. Так делают, когда разработчик заранее знает, какое минимальное количество элементов в массиве ему понадобится. Это позволяет уменьшить количество «перезаписей» массива. Для задания емкости нужно указать в скобках целое число — начальное количество элементов.
Затем можно начинать работать с динамическим массивом: добавлять данные командой .add(element), изменять с помощью .set(index, element), применять к элементам различные функции. Их очень много, и с их списком можно ознакомиться в любом туториале или в документации.
Вы можете подробнее узнать про язык Java и про структуры данных в нем из нашего профессионального курса. Станьте востребованным специалистом с нами.
Java-разработчик
Java уже 20 лет в мировом топе языков программирования. На нем создают сложные финансовые сервисы, стриминги и маркетплейсы. Освойте технологии, которые нужны для backend-разработки, за 14 месяцев.
Статьи по теме:
Структуры данных в картинках. ArrayList
Взбрело мне в голову написать несколько статей, о том как реализованы некоторые структуры данных в Java. Надеюсь, статьи будут полезны визуалам (картинки наше всё), начинающим java-визуалам а также тем кто уже умеет писать new ArrayList(), но слабо представляет что же происходит внутри.
Сегодня поговорим о ArrayList-ах
ArrayList — реализует интерфейс List. Как известно, в Java массивы имеют фиксированную длину, и после того как массив создан, он не может расти или уменьшаться. ArrayList может менять свой размер во время исполнения программы, при этом не обязательно указывать размерность при создании объекта. Элементы ArrayList могут быть абсолютно любых типов в том числе и null.
Создание объекта
ArrayList list = new ArrayList();
Только что созданный объект list, содержит свойства elementData и size.
Хранилище значений elementData есть ни что иное как массив определенного типа (указанного в generic), в нашем случае String[]. Если вызывается конструктор без параметров, то по умолчанию будет создан массив из 10-ти элементов типа Object (с приведением к типу, разумеется).
elementData = (E[]) new Object[10];
Вы можете использовать конструктор ArrayList(capacity) и указать свою начальную емкость списка.
Добавление элементов
list.add("0");
Внутри метода add(value) происходят следующие вещи:
1) проверяется, достаточно ли места в массиве для вставки нового элемента;
ensureCapacity(size + 1);
2) добавляется элемент в конец (согласно значению size) массива.
elementData[size++] = element;
Весь метод ensureCapacity(minCapacity) рассматривать не будем, остановимся только на паре интересных мест. Если места в массиве не достаточно, новая емкость рассчитывается по формуле (oldCapacity * 3) / 2 + 1. Второй момент это копирование элементов. Оно осуществляется с помощью native метода System.arraycopy(), который написан не на Java.
// newCapacity - новое значение емкости elementData = (E[])new Object[newCapacity]; // oldData - временное хранилище текущего массива с данными System.arraycopy(oldData, 0, elementData, 0, size);
Ниже продемонстрирован цикл, поочередно добавляющий 15 элементов:
list.add("1");
.
list.add("9");
list.add("10");
При добавлении 11-го элемента, проверка показывает что места в массиве нет. Соответственно создается новый массив и вызывается System.arraycopy().
После этого добавление элементов продолжается
.
list.add("14");
Добавление в «середину» списка
list.add(5, "100");
Добавление элемента на позицию с определенным индексом происходит в три этапа:
1) проверяется, достаточно ли места в массиве для вставки нового элемента;
ensureCapacity(size+1);
2) подготавливается место для нового элемента с помощью System.arraycopy();
System.arraycopy(elementData, index, elementData, index + 1, size - index);
3) перезаписывается значение у элемента с указанным индексом.
elementData[index] = element; size++;
Как можно догадаться, в случаях, когда происходит вставка элемента по индексу и при этом в вашем массиве нет свободных мест, то вызов System.arraycopy() случится дважды: первый в ensureCapacity(), второй в самом методе add(index, value), что явно скажется на скорости всей операции добавления.
В случаях, когда в исходный список необходимо добавить другую коллекцию, да еще и в «середину», стоит использовать метод addAll(index, Collection). И хотя, данный метод скорее всего вызовет System.arraycopy() три раза, в итоге это будет гораздо быстрее поэлементного добавления.
Удаление элементов
Удалять элементы можно двумя способами:
— по индексу remove(index)
— по значению remove(value)
С удалением элемента по индексу всё достаточно просто
list.remove(5);
Сначала определяется какое количество элементов надо скопировать
int numMoved = size - index - 1;
затем копируем элементы используя System.arraycopy()
System.arraycopy(elementData, index + 1, elementData, index, numMoved);
уменьшаем размер массива и забываем про последний элемент
elementData[--size] = null; // Let gc do its work
При удалении по значению, в цикле просматриваются все элементы списка, до тех пор пока не будет найдено соответствие. Удален будет лишь первый найденный элемент.
Дополнение 1: Как верно заметил MikeMirzayanov, при удалении элементов текущая величина capacity не уменьшается, что может привести к своеобразным утечкам памяти. Поэтому не стоит пренебрегать методом trimToSize().
Итоги
— Быстрый доступ к элементам по индексу за время O(1);
— Доступ к элементам по значению за линейное время O(n);
— Медленный, когда вставляются и удаляются элементы из «середины» списка;
— Позволяет хранить любые значения в том числе и null;
— Не синхронизирован.
Ссылки
Пишите в комментариях пожелания/замечания и есть ли смысл продолжать.
Списочный массив ArrayList
В Java массивы имеют фиксированную длину и не могут быть увеличены или уменьшены. Класс ArrayList реализует интерфейс List и может менять свой размер во время исполнения программы, при этом не обязательно указывать размерность при создании объекта. Элементы ArrayList могут быть абсолютно любых типов в том числе и null.
Пример создания объекта ArrayList
ArrayList list = new ArrayList ();
Можно инициализировать массив на этапе определения. Созданный объект list содержит свойство size. Обращение к элементам массива осуществляется с помощью метода get(). Пример :
ArrayList list; list = Arrays.asList(new String[] ); System.out.println ("Размер массива равен '" + Integer.valueOf (list.size()) + "' элементам");
Добавление элемента в массив ArrayList, метод add
Работать с ArrayList просто: необходимо создать объект и вставлять созданные объекты методом add(). Обращение к элементам массива осуществляется с помощью метода get(). Пример:
ArrayList list; list = new ArrayListЗамена элемента массива ArrayList, метод set
Чтобы заменить элемент в массиве, нужно использовать метод set() с указанием индекса и новым значением.
list.add("Яблоко"); list.add("Груша"); list.add("Слива"); list.set(1, "Персик"); System.out.println ( "2-ой элемент массива '" + list.get(1) + "'");Удаление элемента массива ArrayList, метод remove
Для удаления элемента из массива используется метод remove(). Можно удалять по индексу или по объекту:
list.remove(0); // удаляем по индексу list.remove("Слива"); // удаляем по объектуПРИМЕЧАНИЕ: элементы, следующие после удалённого элемента, перемещаются на одну позицию ближе к началу. То же самое относится и к операции вставки элемента в середину списка.
Для очистки всего массива используется метод clear():
list.clear();Определение позиции элемента ArrayList, метод indexOf
В списочном массиве ArrayList существует метод indexOf(), который ищет нужный элемент и возвращает его индекс.
int index = list.indexOf("Слива"); // выводим имя элемента и его номер в массиве System.out.println (list.get(index) + " числится под номером " + index);Отсчёт в массиве начинается с 0, если индекс равен 2, значит он является третьим в массиве.
Проверка наличие элемента в ArrayList, метод contains
Чтобы узнать, есть в массиве какой-либо элемент, можно воспользоваться методом contains(), который вернёт логическое значение true или false в зависимости от присутствия элемента в наборе :
System.out.println (list.contains("Картошка") + "");Понятно, что в массиве никаких овощей быть не может, поэтому в консоле будет отображено false.
Создание массива из элементов ArrayList, метод toArray
Для конвертирования набора элементов в обычный массив необходимо использовать метод toArray().
ArrayList myArrayList = new ArrayList(); myArrayList.add("Россия"); myArrayList.add("Польша"); myArrayList.add("Греция"); myArrayList.add("Чехия"); String[] array = <>; // конвертируем ArrayList в массив array = myArrayList.toArray(new String[myArrayList.size()]);Интерфейс List
java.util.List является интерфейсом и его следует использовать вместо ArrayList следующим образом :
List list = new ArrayList();Или укороченный вариант для Java 7:
List list = new ArrayList<>();В примере тип ArrayList заменен на List, но в объявлении оставлен new ArrayList(). Всё остальное остаётся без изменений. Это является рекомендуемым способом.
Интерфейс List реализует более общий интерфейс коллекции Collection.
Преобразование массива в список, Arrays
Для создания массива можно не только добавлять по одному объекту через метод add(), но и сразу массив с использованием Arrays.asList(. ).
Пример создания и инициализации массива из объектов Integer.
List numlist = Arrays.asList(1, 2, 5, 9, 11); System.out.println (numlist.get(2) + ""); // выводит число 5У данного способа есть недостаток. Если вы определили списочный массив таким образом, то уже не можете вставлять или удалять элемент, хотя при этом можете изменять существующий элемент.
List numlist = Arrays.asList(1, 2, 5, 9, 11); numlist.set(2, 33); // так можно numlist.add(34); // нельзя, ошибка во время исполнения System.out.println (numlist.get(2) + "");