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);
2
Задача
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.

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

Комментарии (130)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий вы должны авторизоваться
progr7 уровень
понедельник, 23:08
for(int i = 0; i < 5; i++) { String s = bufferedReader.readLine(); list.add(s); при таком раскладе при вводе по очереди а, б, г, в, д. а затем если вывести вот это System.out.println(list.get(0)); выводится элемент "а" то есть элемент первой ячейки. Но есть одно но в лекции написано list.add(s); добавление в конец массива. Получается элеамент "а" должен быть в пятой ячейке(точнее если говорить по синтаксису под номером 4). Почему тогда "а" в ячейке под номер "0"?
Никита8 уровень, Днепр
позавчера, 18:56
почему? Вот идет итерация: i = 0 list[0] = a ( 0 - это конец массива на данный момент ) i = 1 list[1] = б ( 1 - это на текущий момент конец массива) .... i = 4 list[4] = г ( сейчас длина 4 элемента, поэтому 5тым будет "г" как раз конец массива )
Роман12 уровень, Москва
14 августа, 11:55
Создание массива
ArrayList<String> cars = new ArrayList<String>(); //Создание массива
Метод add(); - Добавление в массив
cars.add(0,"niva");//Добавление в массив
cars.add(1,"volga");
 cars.add(2,"BMV");
Метод get(); - взятие значения элемента массива
String BMV = cars.get(2);//Взятие значения элемента массива
System.out.println(BMV);
Метод size() - Получение размера массива
int size = cars.size();//Получение размера массива
System.out.println(size);
Метод set() - Замена(или запись) элемента массива вместо другого элемента
cars.set(0, "porshe");//Замена(или запись) элемента массива вместо другого элемента
System.out.println(cars.get(0));//
Метод remove() - Удаление. Удалять можно как по значению, так и по индексу.
cars.remove(2);//Удаление элемента массива
cars.remove("volga");
Метод clone() -Клонирование массива в другой массив.
ArrayList<String> cars_second_list = (ArrayList<String>)cars.clone();//Клонирование массива в другой массив
System.out.println(cars_second_list.get(0));
Метод clear () - Очищение массива.
cars_second_list.clear();
Метод isEmty() - Проверяет пустой ли массив. Если да - true, нет - false;
boolean empty_of_massive = cars_second_list.isEmpty();//Проверяет пустой ли массив. Если да - true, нет - false;
 System.out.println(empty_of_massive);
Роман12 уровень, Москва
14 августа, 11:56
Метод contains() - Поиск по содержание. Если есть - true, нет - false;
boolean result_search_of_car =cars.contains("porshe");//Поиск по содержаниею
        System.out.println(result_search_of_car);
Метод ensureCapacity() -Задать емкость массива
cars.ensureCapacity(7);//Задать емкость
        cars.set(8,"gigul");//Выдаст ошибку так как индекс массива выше заданной емкости
Дальше мне уже лень писать) Подробнее на официальном сайте
Intern10 уровень, Riga
10 июля, 16:57
кто то может объяснить про Добавление элемента в конец массива Arraylist? Тут в примере ArrayList<String> list = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String s = reader.readLine(); list.add(s); <---- из теории я понял, что list.add(s); это добавлениe в конец массива, а тут получается что добавляется элемент в начало, как с простым массивом. Хотя по логике мы должны были сюда вписать list.add(i, s).???
Viktor Gromov11 уровень
23 июля, 04:01
Метод add(s) добавляет запись в конец Вот заполнение обычного массива:
String[] list = new String[10];
for (int i = 0; i < list.length; i++) {
  String s = reader.readLine();
  list[i] = s;
}
Здесь происходит добавление нового элемента от i = 0 до i = 9 элемента включительно. Суть не так важна, можно было бы спокойно записать заполнение и с середины, и с конца. В данном же случае
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < 10; i++){
  String s = reader.readLine();
  list.add(s);
}
метод add добавляет запись именно в конец массива. Мы не можем назвать ситуацию по заполнению массива в первом случае как "добавление записи в конец", ведь массив у нас определенной длинны (10) и при, скажем, пятом проходе цикла будет заполнен i = 4 элемент, а это никак не конец. Метод add(s) добавляет запись именно в конец массива. В этой лекции уже говорилось, что главная прелесть этого класса в том, что у него нет фиксированной длины. Поэтому если вы решите добавить туда 5 элементов, то длина массива будет 5. Припишите туда еще 3 элемента, длина уже 8. Удалите 2 - длина 6. А этот метод каждый раз как бы расширяет массив на единицу и вписывает в освободившуюся в конце ячейку новое значение. Вы уже проходили, что методы могут называться одинаково, но они будут считаться разными, если у них разный набор аргументов. Поэтому метод add(i, s) - это совершенно другой метод, который добавляет запись не в конец, как это делает наш метод add(s), а в определенное место в массиве. Работает он похоже: все элементы, начиная с указанного номера i передвинутся вправо (на позицию выше), а в освободившееся место запишется значение s. То есть
add(s) != add(0, s)
progr7 уровень
понедельник, 09:09
если говорить точнее add(s) это метод по умолчанию как бы, а add(0, s) мы намеренно добавляем значение в определенное место в массиве(по индексу конечно же), и в нашем случае мы добавляем значение s в массив по индексу 0, то есть в первую ячейку
Olha Pokotylo8 уровень, Киев
29 июня, 21:44
А что происходит при записи в середину массива, если там уже было значение? На примере экселя: это будет вставка новой ячейки с указанным значением ("со сдвигом вправо"), или перезапись в ту же ячейку, старое значение удалится?
Ваня Петило17 уровень, Львов
30 июня, 14:43
Будет добавлено с сдвигом вправо. То есть, существующий элемент будет сдвинут вправо, а на его место добавлен тот, что вы просите.
Ваня Петило17 уровень, Львов
30 июня, 15:07
Все вышенаписанное актуально для add Если необходимо перезаписать - используйте set
Захар12 уровень, Москва
17 июля, 11:22
Станислав Рухляда17 уровень, Москва
29 июня, 16:02
list.add(15, s); почему это вставка в СЕРЕДИНУ массива ?
sempad8 уровень
7 августа, 15:58
Условно в середину. Имеется ввиду, что в 15 ячейку будет записано значение s. Значение из 15 ячейки сдвинется в 16, из 16 в 17 и так далее. Если же нужно не просто воткнуть, а именно изменить/перезаписать значение конкретной ячейки, не двигая остальные, то используется метод set.
misty22 уровень, Пермь
25 июня, 20:00
Элли, ты очень вовремя с ArrayList! Даже не представляешь как!
Сергей Novichok11 уровень, Нижний Новгород
17 июня, 16:54
А что с Паскалем? Помню, это был главный геморрой с жестким ограничением по длине массивов
GigaMax12 уровень
27 апреля, 07:42
Всё понятно)
Самуил Олегович25 уровень, Киев
26 апреля, 14:27
В 11—й строке можно было бы и так вставлять элементы в лист массив — list.set(i, s); или я ошибаюсь? И аdd не надо.
GigaMax12 уровень
27 апреля, 07:16
Там нельзя использовать set, так как длина списочного массива ещё не задана и эта команда создаст ошибку
Самуил Олегович25 уровень, Киев
27 апреля, 10:01
выходит сетом можно пользоваться только уже в сформированном массиве?
GigaMax12 уровень
27 апреля, 19:44
я думаю, что можно и в пустом, но инициализированном с заданным количеством элементов, например:
ArrayList<String> line = new ArrayList<>(5);  // Тут можно будет использовать set
Самуил Олегович25 уровень, Киев
28 апреля, 10:10
Спасибо, за разбор.
Ihor10 уровень, Киев
8 мая, 09:38
Подскажите, почему new ArrayList<>(5) без new ArrayList<String>(5)???
GigaMax12 уровень
10 мая, 05:43
Мы можем указать один раз тип данных(полная запись не обязательна, компилятор это понимает), например: String, в типе переменной ArrayList при объявлении. Это было в лекциях: ArrayList<String> list = new ArrayList<>(); ArrayList<Integer> number = new ArrayList<>(); и т.д.
Ihor10 уровень, Киев
10 мая, 14:29
Спасибо)
S22 уровень, Минск
17 июля, 21:30
Это называется "алмаз" - синтаксический сахар, добавленный для того, что бы не писать тип второй раз.
Ihor10 уровень, Киев
19 июля, 08:10
спасибо!
Дмитрий26 уровень
1 апреля, 12:20
Не пойму в чем разница между записать элемент в массив (set) т добавить элемент в массив (add)
George34 уровень
1 апреля, 18:23
Ниже был ответ: Метод set просто меняет значение элемента по определенному индексу с одного на другое, а метод add вставляет новый элемент на определенный индекс. То есть в первом случае количество элементов остается тем же, а во втором - увеличивается на 1.
progr7 уровень
понедельник, 09:15
да, верно описал Георг. add добавляем новый элемент в определенную ячейку со сдвигом существующих элементов вправо, а set просто значение, без изменения количества ячеек. в общем set тоже самое что мы делаем тут int i = 5; и далее мы меняем значение i = 6;