Для того, чтобы было удобно управлять данными, их зачастую приходится хранить вместе как единый набор переменных. В языке Java, как и в других языках программирования, существуют массивы. Однако массивы неповоротливы. Их размер постоянен, и чтобы добавить или удалить элемент, приходится создавать новый массив.
В отличие от массивов, списки (list) предоставляют куда более широкий функционал. Давайте поговорим о таком понятии, как список, в целом, а также о двух реализациях списка в Java – ArrayList и LinkedList.
Содержание:
List
В Java есть такой интерфейс – List. Он определяет основные методы для работы с набором данных. У этого интерфейса могут быть разные реализации (например, ArrayList и LinkedList), но снаружи не видно, что под капотом. Поэтому работаем мы с ними одинаковым образом – через методы, определённые в интерфейсе List. Так пахнет полиморфизм, один из четырёх китов ООП.
Итак, давайте разберёмся с основными методами, которые чаще всего пригождаются при работе со списками. Перед началом работы со списком нужно его создать. Чтобы создать список строковых переменных (String), нужно написать это:
1 |
List<String> fruits = new ArrayList<>(); |
Или вот это:
1 |
List<String> fruits = new LinkedList<>(); |
Что будет справа, зависит от того, какую реализацию списка вы хотите использовать в конкретном случае. Однако то, что слева, постоянно, так как методы для работы со списком едины для всех реализаций интерфейса List.
После создания список пустой – имеет 0 элементов. Но это ненадолго. Добавить элемент в список можно методом add():
1 2 3 |
fruits.add("Банан"); fruits.add("Ананас"); fruits.add("Киви"); |
Теперь список содержит три элемента – “Банан”, “Ананас” и “Киви”.
Для того, чтобы заменить один элемент на другой, нужно использовать метод set() с указанием двух параметров – индекса заменяемого элемента и нового значения:
1 |
fruits.set(1, "Апельсин"); |
Элемент с индексом 1 (“Ананас”) был заменён на “Апельсин”. Теперь список выглядит так: “Банан”, “Апельсин” и “Киви.
Для того, чтобы получить элемент списка, применяется метод get() с указанием индекса элемента, к которому нужно получить доступ:
1 |
System.out.println(fruits.get(0)); |
Так как нулевой элемент – “Банан”, то он и выведется в консоль.
Чтобы удалить элемент из списка, можно воспользоваться методом remove(). Можно указать как сам удаляемый объект, так и его индекс.
Удаление по самому объекту:
1 |
fruits.remove("Киви"); |
Удаление по индексу:
1 |
fruits.remove(2); |
Обе команды приведут к одному и тому же результату, к удалению элемента №2 – “Киви”.
Чтобы полностью очистить список от элементов, используется метод clear():
1 |
fruits.clear(); |
Для того, чтобы узнать размер списка, нужно вызвать метод size(). Он возвращает число элементов списка типа int. Пример его применения в условии if:
1 2 3 |
if (fruits.size() > 2) { ... } |
А чтобы выяснить, содержится ли указанный объект в списке, вызывается метод contains(). Он возвращает значение типа boolean. Важно понимать, что contains() проходится по списку, сравнивая имеющиеся в нём элементы с указанным при помощи метода equals(). Пример использования метода contains() в условии:
1 2 3 |
if (fruits.contains("Банан")) { ... } |
ArrayList
ArrayList – это одна из реализаций интерфейса List в Java. Под капотом ArrayList имеет в себе массив. То есть элементы хранятся в непрерывной области памяти – им друг до друга рукой подать.
Однако реализовано это всё чуть хитрее, чем пересоздание этого массива каждый раз при изменении количества элементов списка. Когда вы добавляете новый элемент в ArrayList и количество элементов приближается к текущей ёмкости массива, ArrayList увеличивает размер своего внутреннего массива. Обычно это происходит с некоторым запасом, чтобы уменьшить частоту пересоздания массива. Имеется также механизм для уменьшения размера массива при удалении элементов.
Благодаря массиву доступ к элементам по индексу осуществляется быстро и за постоянное время. Более того, ArrayList использует меньше памяти, чем LinkedList.
LinkedList
В свою очередь, LinkedList реализован как двусвязный список. Это означает, что каждый элемент содержит ссылку на предыдущий и следующий элемент.
Доступ к элементам по индексу происходит медленнее, чем в ArrayList. Зато быстрее выполняются операции вставки и удаления. Памяти LinkedList занимает больше, чем ArrayList, так как для каждого своего элемента ему приходится хранить 2 дополнительные переменные: ссылка на предыдущий и ссылка на следующий элемент.
На практике вам скорее всего пригодится именно ArrayList. LinkedList, на самом деле, нужен для узких задач, и только если сильно надо оптимизировать время некоторых операций. А так, использование списков вместо массивов очень упрощает жизнь.