Class ArrayList

Открыта

— А вот и я.

— Привет, Элли!

— Сегодня новая интересная тема! Сейчас я расскажу тебе о новом интересном классе — ArrayList.

— О, новый класс? Круто! И что он умеет делать?

— Начну с небольшой предыстории. Программистам очень не нравилось одно свойство массива – его размер нельзя изменять. Что делать, если нужно сохранить в массиве ещё три элемента, а свободное место только одно?

— Единственным решением проблемы нехватки места в массиве было создание массива очень большого размера, чтобы все элементы туда точно поместились. Но это часто приводило к нерациональному расходу памяти. Если чаще всего в массиве хранилось три элемента, но был хотя бы мизерный шанс, что там их будет 100, приходилось создавать массив на 100 элементов.

— И что же придумали программисты?

— Они написали класс ArrayList (списочный массив), который выполнял ту же работу, что и Array (массив), но мог изменять свой размер.

— Интересный ход. И как же они это сделали?

— Внутри каждого объекта типа ArrayList хранится обычный массив элементов. Когда ты считываешь элементы из ArrayList, он считывает их из своего внутреннего массива. Когда записываешь – записывает их во внутренний массив. Вот сравни:

Array ArrayList
Создание контейнера элементов
String[] list = new String[10];
ArrayList<String> list = new ArrayList<String>();
Получение количества элементов
int n = list.length;
int n = list.size();
Взятие элемента из массива/коллекции
String s = list[3];
String s = list.get(3);
Запись элемента в массив
list[3] = s;
list.set(3, s);

— И в чем же преимущество ArrayList? Как по мне, так код стал длиннее.

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

— Во-вторых, изменение размера: когда нужно записать во внутренний массив ещё один элемент, а свободного места там нет, то внутри ArrayList делается вот что:

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

б) все элементы из старого массива копируются в новый массив.

в) новый массив сохраняется во внутренней переменной объекта ArrayList, старый массив объявляется мусором (мы просто перестаём хранить на него ссылку).

Array ArrayList
Добавление элемента в конец массива
Невозможно выполнить данное действие
list.add(s);
Вставка элемента в середину массива
Невозможно выполнить данное действие
list.add(15, s);
Вставка элемента в начало массива
Невозможно выполнить данное действие
list.add(0, s);
Удаление элемента из массива
Можно стереть элемент с помощью list[3] = null. Но тогда останется «дыра» в массиве.
list.remove(3);
8
Задача
Java Syntax,  7 уровень,  5 лекция
Недоступна
Набираем код
Иногда думать не надо, строчить надо! Как ни парадоксально звучит, порой пальцы «запоминают» лучше, чем сознание. Вот почему во время обучения в секретном центре JavaRush вы иногда встречаете задания на набор кода. Набирая код, вы привыкаете к синтаксису и зарабатываете немного материи. А ещё — боретесь с ленью.

— А как работать с этим ArrayList’ом?

— А практически так же, как и с массивом. Вот смотри. Давай сравним работу с ArrayList с работой с массивом. Для примера решим такую задачу «ввести 10 строк с клавиатуры и вывести их на экран в обратном порядке» .

— Смотри:

Используем Array
public static void main(String[] args)
{
Reader r = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(r);

//ввод строк с клавиатуры
String[] list = new String[10];
for (int i = 0; i < list.length; i++)
{
  String s = reader.readLine();
  list[i] = s;
}

//вывод содержимого массива на экран
for (int i = 0; i < list.length; i++)
{
  int j = list.length - i - 1;
  System.out.println( list[j] );
}
}
Используем ArrayList
public static void main(String[] args)
{
Reader r = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(r);

//ввод строк с клавиатуры
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < 10; i++)
{
  String s = reader.readLine();
  list.add(s);
}

//вывод содержимого коллекции на экран
for (int i = 0; i < list.size(); i++)
{
  int j = list.size() - i - 1;
  System.out.println( list.get(j) );
}
}

— Я раскрасила одним цветом эквивалентные действия в обеих колонках.

— С одной стороны все по-другому, с другой – все осталось тем же самым.

— Ага. Только мы теперь не используем квадратные скобочки при работе с Class ArrayList. Вместо них мы используем методы get, set и add.

— Да, я уже заметил. Но все равно очень похоже.

Комментарии (101)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий вы должны авторизоваться
Дмитрий10 уровень
1 апреля, 12:20
Не пойму в чем разница между записать элемент в массив (set) т добавить элемент в массив (add)
George19 уровень
1 апреля, 18:23
Ниже был ответ: Метод set просто меняет значение элемента по определенному индексу с одного на другое, а метод add вставляет новый элемент на определенный индекс. То есть в первом случае количество элементов остается тем же, а во втором - увеличивается на 1.
RustiG13 уровень, Санкт-Петербург
19 февраля, 13:37
а что это за <> скобки такие? они используются только в ArrayList для указания типа?
Владислав16 уровень, Москва
24 февраля, 08:17
В них указывается, объекты какого класса мы будем в него вкладывать. Вообще для любого класса-контейнера (ArrayList один из них) компилятору нужно знать, что будет внутри, поэтому придумали так указывать.
Hexronimo17 уровень
24 февраля, 09:25
В коллекциях еще (они позже будут изучаться).
RustiG13 уровень, Санкт-Петербург
25 февраля, 18:03
Спасибо
Dmitry16 уровень, Екатеринбург
9 февраля, 15:15
Массивами пользоваться не имеет смысла, если есть коллекции, такой вывод?
Hexronimo17 уровень
24 февраля, 09:37
В коллекции вы можете хранить толко объекты, т.е. ArrayList<Integer> но не ArrayList<int>, объекты занимают больше памяти чем примитивы (https://habr.com/en/post/134102/), так что нужно делать выбор в зависимости от задачи. По крайней мере мне так кажется :)
АртемGeek13 уровень, Москва
5 апреля, 14:58
Добавлю также, Array хороши когда не знаешь точное кол-во элементов в массиве, потому что он расширяем.
Arjuna9 уровень
19 января, 17:53
обьясните плз разницу между set(10,s) и add(10,s) - в обоих случаях добавляем элемент s в ячейку 10?
Богдан18 уровень, Киев
20 января, 00:48
Метод set просто меняет значение элемента по определенному индексу с одного на другое, а метод add вставляет новый элемент на определенный индекс. То есть в первом случае количество элементов остается тем же, а во втором - увеличивается на 1.
Михаил Кузьмин 22 уровень, Новосибирск
27 декабря 2018, 16:28
Как называется метод, проверяющий строку на содержание данного символа??
Veronika Nikitina14 уровень, Санкт-Петербург
30 декабря 2018, 20:48
Contains?
Artur41 уровень
25 декабря 2018, 10:10
Как же заморочно в java с массивами, в js это намного проще всё реализовано
AlexEremenko18 уровень
5 января, 08:55
Это ты еще Паскаль не видел ;)
Aliaksandr.Pitkevich11 уровень, Минск
21 января, 15:22
мой первый ЯП Javascript, Java для себя изучаю. Хоть в JS и по проще с массивами, но гибкости больше в джаве
victor19 уровень
15 декабря 2018, 20:07
объясните пожалуйста как работает это вариант вывода содержимого массива на экран в обратном порядке for (int i = 0; i < list.length; i++) { int j = list.length - i - 1; System.out.println( list[j] ); }
Alex20 уровень, Санкт-Петербург
16 декабря 2018, 01:05
int j = list.length - i - 1; данная конструкция присваивает j значения начиная с самого большого индекса массива до самого маленького (т.е. до 0) точнее: list.length - дает цифру равную колличеству элементов массива. Данная цифра на 1 больше самого большого индекса массива, ибо индексация начинается от 0 , а не от 1. Поэтому от нее отнимается 1: list.length - 1 - получили самый большой индекс для массива. Далее уменьшаем его по очереди на 1 вычитая i которое последовательно увеличивается с 0 до максимального индекса. Для наглядности подставьте цифры, и попробуйте на бумажке рассписать хотя бы несколько шагов этого куска программы, подставляя сначала вместо i числа от 0 и далее. А вместо list.length цифру равную колличеству элементов массива, например 10.
victor19 уровень
16 декабря 2018, 07:57
-1 я понял а что делает -i ведь он тоже участвует в операций .зачем? по моему я понял -1 он только для того чтобы начать отсчет от последнего индекса -i для (-0,-1,-2,-3... итд).Правильно ли я понял?
Alex20 уровень, Санкт-Петербург
16 декабря 2018, 19:28
так если i не отнимать число не изменится. i меняется в условии цикла от 0 до длины массива. соответственно отнимая i мы последовательно уменьшаем число на 1цу и получаем последовательность: n, .... , 4, 3, 2, 1, 0
victor19 уровень
16 декабря 2018, 19:41
ну да если минус я описал операцию а вывод конечно будет как у тебя
jaymz17 уровень, Екатеринбург
24 декабря 2018, 18:40
Я использую такую конструкцию:
for (int i = array.length - 1; i >=0; i--) {
    System.out.println(array[i]);
Как по мне - это более понятно и меньше печатать.
victor19 уровень
24 декабря 2018, 20:43
я тоже привык к такой но пытаюсь освоить и другие варианты а то разных писателей надо читать
UnNameD16 уровень, Москва
8 октября 2018, 11:55
Почему при занесении введенного значения в массив используется add а не set?
Танюшка Березенцева8 уровень, Тюмень
10 октября 2018, 11:05
могу ошибаться, но в случае set мы не увеличиваем длину самой коллекции, а устанавливаем новое значение уже имеющейся ячейке (поэтому два параметра требуется - адрес ячейки и значение). А add просто добавляет еще одну ячейку памяти на хвост ArrayList -у с новым значением.
Timur Gilauri18 уровень
11 октября 2018, 04:50
set - это метод, позволяющий задать значение элементу списка под нужным индексом, при условии, что данный индекс есть в списке. Например:
ArrayList<String> list = new ArrayList<String>();
list.add("ads"); // Теперь в списке есть один элемент, индекс которого - 0
System.out.println(list.get(0)); // ads
list.set(0, "qwerty"); // Теперь в ячейке списка с индексом 0 содержится переданное значение
System.out.println(list.get(0)); // qwerty
Однако, такое:
list.set(1, "new line");
Выкинет ошибку:
Index 1 out-of-bounds for length 1
list.set(1, "new line")
Потому что в данном списке нет индекса под номером 1.
Никита Власов10 уровень, Минск
22 сентября 2018, 22:16
В статье говорят, что ArrayList это класс, т.е. обьект должен создаваться по типу
new ArrayList();
почему в примерах фигурирует
ArrayList<String> list = new ArrayList<String>();
Вячеслав20 уровень, Санкт-Петербург
24 сентября 2018, 11:21
Это так называемый параметризованный тип данных. По сути в коллекциях мы можем хранить объекты любых разных типов. А данная фраза говорит о том, что мы создаём коллекцию list, в которой будут храниться только строки. Т.е. нечего кроме объекта String туда будет не засунуть. Это сделано для своего рода безопасности, чтобы уже на стадии компиляции выполнялась проверка, не пытаемся ли мы засунуть в коллекцию что-то лишнее. Кстати, в современной версии Java необязательно писать String во втором случае. Достаточно ArrayList<String> list = new ArrayList<>();
Tyrant10 уровень
22 октября 2018, 17:55
То есть если мы напишем new ArrayList<> - проверка выполнится, а если без <>, то проверка не происходит, верно?
Вячеслав20 уровень, Санкт-Петербург
24 октября 2018, 10:59
Если мы создаём ссылку ArrayList<String> list (говоря по сути, что по этой ссылке будет лежать коллекция с объектами типа String), то при создании объекта всё равно придётся написать либо new ArrayList<String>(), либо new ArrayList<>(). В этом случае проверка выполняется. Если мы напишем ArrayList list = new ArrayList(), то в такую коллекцию можно засунуть объект любого типа - компилятор не будет ругаться.
Tyrant10 уровень
24 октября 2018, 11:35
Ок. Спасибо.
SanD28 уровень
13 июля 2018, 13:40
Подскажите смысл переменной j в последнем примере, почему просто через i нельзя вывести на экран?
SanD28 уровень
14 июля 2018, 14:57
Спасибо, не заметил условие задачи. Еще можно поменять условие в цикле, начинать не с нуля а с длины списка -1, и минусовать. Тогда выводить на экран прямо через i можно без дополнительный действий. Правильно?
Дмитрий22 уровень
18 июля 2018, 01:41
Правильно. Предыдущие задания именно так сдавал.