Коллекции в Java
Java Коллекции являются одним из столпов Java Core. Они используются почти в каждом приложении, поэтому мы просто обязаны уметь использовать Java Collections Framework эффективно.
Что такое Коллекции?
Коллекции — это контейнеры, группы элементов, которые представляют собой единое целое.
Например: банка конфет, список имен и т.д. Коллекции используются почти в каждом языке программирования и Java не является исключением. Как только коллекции появились в Java, то насчитывали всего несколько классов: Vector, Stack, Hashtable, Array. Но уже в Java 1.2 появился полноценный Java Collections Framework, с которым мы и будем сегодня знакомиться.
Коллекции в Java состоят нескольких частей
- Интерфейсы: В коллекциях интерфейсы обеспечивают абстрактный тип данных для представления коллекции
java.util.Collection
— корневого интерфейса фреймворка. Он находится на вершине иерархии Коллекций. Он содержит наиболее важные методы:size()
,iterator()
,add()
,remove()
,clear()
. Каждая коллекция должна реализовывать эти методы. Также есть другие важные интерфейсыjava.util.List,
java.util.Set,java.util.Queue
иjava.util.Map
.Map
является единственным интерфейсом, который не наследует интерфейсCollection
, но является неотъемлемой частью коллекций. Все интерфейсы фреймворка находятся в пакетеjava.util
. - Реализация: Java предоставляет готовые классы с реализацией вышеупомянутых коллекций. Мы можем использовать их для создания новых типов коллекций в нашей программе. С помощью классов
ArrayList, LinkedList, HashMap, TreeMap, HashSet, TreeSet
можно решить огромное количество задач, но если нам нужна специальная реализация той или иной коллекции, мы можем наследовать её и работать со своей реализацией. В Java 1.5 придумали потокобезопасные коллекции, которые позволили изменять содержимое коллекции время итерации по элементам. Наиболее популярными являются:CopyOnWriteArrayList,
ConcurrentHashMap,
CopyOnWriteArraySet.
Эти классы находятся в пакетеjava.util.concurrent
. Все классы коллекций находятся в пакетахjava.util
иjava.util.concurrent
. - Алгоритмы: алгоритмы — это полезны методы, которые решают тривиальные задачи, например: поиск, сортировка и перетасовка элементов коллекции.
- Ниже на диаграмме классов показана иерархия Java Collections Framework. Для простоты я включил только часто используемые интерфейсы и классы.
Преимущества Java Collections Framework
В Java Collections Framework есть следующие преимущества:
- Требует меньше усилий. Фреймворк располагает множеством распространенных типов коллекций и полезных методов для манипуляции данными. Таким образом, мы можем сосредоточиться на бизнес-логике, а не разработке наших API.
- Отличное качество — использование хорошо проверенных коллекций увеличивает качество нашей программы.
- Повторное использование и совместимость
Интерфейсы коллекций
Интерфейсы являются основой Java Collections Framework. Обратите внимание, что все интерфейсы являются Generic, например public interface Collection<E>
. Использование <E>
— это указание типа объекта, который коллекция может содержать. Это помогает сократить ошибки времени выполнения с помощью проверки типов объектов во время компиляции.
Следует отметить, что платформа Java не предоставляет отдельные интерфейсы для каждого типа коллекций. Если какая-то операция не поддерживается, то реализация коллекции бросает UnsupportedOperationException.
Кратко по каждой коллекции
Интерфейс итератора (Iterator)
Итератор предоставляет методы для перебора элементов любой коллекции. Мы можем получить экземпляр итератора из коллекции с помощью метода iterator
. Итераторы позволяют удалить элементы из базовой коллекции во время выполнения итерации.
Интерфейс множества (Set)
Набор представляет собой коллекцию, которая не может содержать повторяющиеся элементы. Этот интерфейс представляет математическую абстракцию для представления множеств в виде колоды карт.
Платформа Java содержит три реализации Set : HashSet,
TreeSet
и LinkedHashSet.И
нтерфейс Set
не позволяет осуществлять произвольный доступ к элементу в коллекции. Мы можем использовать итератор или цикл по каждому элементу для перебора элементов.
Интерфейс Список (List)
Список представляет собой упорядоченный набор элементов и может содержать повторяющиеся элементы. Вы можете получить доступ к любому элементу по индексу. Список представляет собой динамический массив. Список является одним из наиболее используемых типов коллекций. ArrayList
и LinkedList
классы являются реализацией интерфейса List
.
Вот небольшой пример использования:
1 2 3 4 5 6 7 8 9 |
List strList = new ArrayList<>(); //добавить в конец strList.add(0, "0"); //добавить элемент в определенное место strList.add(1, "1"); //заменить элемент strList.set(1, "2"); //удалить элемент strList.remove("1"); |
Интерфейс Очередь (Queue)
Очередь — коллекция, которая используется для хранения нескольких элементов.
В очереди обычно, но не обязательно, элементы располагаются по принципу FIFO (first-in, first-out = первый вошел, первый вышел). В очереди FIFO, все новые элементы вставляются в конец очереди.
Интерфейс Dequeue
Коллекция Dequeue поддерживает вставку элемента и удаление элемента как в начало, так и в конец коллекции. Название Deque это сокращение от «двухконцевой очереди» и, как правило, произносится как «deck». Большинство реализаций DEQUE не устанавливают ограничения на количество элементов.
Этот интерфейс определяет методы для доступа к элементам на концах дека. Методы предоставляются для вставки, удаления, извлечения элемента.
Интерфейс Map
Map является объектом, который содержит ключи и значения. Map не может содержать дубли ключей: Каждый ключ может иметь только одно значение.
Платформа Java содержит три реализации Map: HashMap,
TreeMap
и LinkedHashMap.
Интерфейс ListIterator
ListIterator (итератор для списков) позволяет программисту проходить список в любом направлении, изменять список во итерации, и получать текущую позицию итератора в списке.
Интерфейс SortedSet
SortedSet представляет собой множество, в котором элементы хранятся в порядке возрастания.
Интерфейс SortedMap
SortedMap содержит элементы в порядке возрастания ключей. Эта Map является аналогом SortedSet. SortedMap используются для естественно упорядоченных пар ключ/значение, например, словарей и телефонных справочников.
Классы реализующие Java коллекции
Java Collections framework предоставляет большое количество классов с реализацией интерфейсов коллекций. Наиболее используемыми и распространенными реализациями являются ArrayList
, HashMap
и HashSet
. Обычно классы, реализующие коллекции, не являются потокобезопасными.
Далее в этой статье мы разберем наиболее используемые классы в Java Collections framework.
HashSet Класс
Это базовая реализация интерфейса Set
, которая базируется на HashMap
.
Этот класс предлагает одинаковое время выполнения базовых операций (add,
remove
, contains
и size
)
. Мы можем установить начальную емкость и коэффициент нагрузки для этой коллекции.
Класс TreeSet
NavigableSet
создан на основе TreeMap.
Элементы могут быть упорядочены в порядке их добавления или с помощью компаратора.
Эта реализация обеспечивает log(n) время выполнения для основных операций (add, remove
и contains
).
Класс ArrayList
ArrayList — реализация интерфейса List в виде массива переменной длины. Реализует все операции со списком. Плюс к этому ArrayList обеспечивает методы для манипулирования размером массива, который используется для хранения списка. (Этот класс примерно соответствует вектору, но не является synchronized
).
LinkedList класс
LinkedList — реализация интерфейсов List и Deque в виде двусвязного списка. Осуществляет все дополнительные операции со списком.
Класс HashMap
HashMap представляет собой реализацию интерфейса Map. Эта реализация обеспечивает все дополнительные операции Map и позволяет нулевые значения и ключи со значением null
. Класс HashMap
примерно эквивалентно Hashtable
, кроме того, что он не синхронизирован и позволяет null
. Этот класс не дает никаких гарантий упорядоченного размещения элементов.
Класс TreeMap
TreeMap представляет собой красно-черное дерево, основанное на NavigableMap. Map сортируются с помощью компаратора.
Эта реализация обеспечивает log(n) время выполнения для операций containsKey, get, put
и remove
.
Класс PriorityQueue
В очереди элементы додаются в порядке FIFO, но иногда мы хотим добавлять элементы на основании их приоритета. В этом случае мы можем использовать PriorityQueue, обеспечив при этом реализацию компаратора для элементов PriorityQueue. Следует отметить, что PriorityQueue не позволяют хранить null
Класс Collections
Этот класс состоит исключительно из статических методов, которые работают или возвращают коллекции. Он содержит полиморфные алгоритмы, которые используются при работе с коллекциями.
Этот класс содержит методы основных алгоритмов Сollection framework, а именно методы бинарного поиска, сортировка, перемешивание, а также метод, возвращающий обратный порядок элементов и многие другие.
Синхронизированные оболочки
Синхронизированные оболочки добавляют автоматическую синхронизацию (потоко-безопасность) к определенной коллекции. Каждый из шести основных интерфейсов коллекций (Collection, Set, List, Map, SortedSet
, и SortedMap
) располагает статическим фабричным методом синхронизации.
1 2 3 4 5 6 |
public static Collection synchronizedCollection(Collection c); public static Set synchronizedSet(Set s); public static List synchronizedList(List list); public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m); public static SortedSet synchronizedSortedSet(SortedSet s); public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m); |
Каждый из этих методов возвращает синхронизированную (потокобезопасную) коллекцию.
Неизменяемые оболочки
Неизменяемые оболочки/обертки не позволяют изменять коллекцию, перехватывая все операции, которые изменяют коллекции и бросают UnsupportedOperationException
в том случае, если кто-то захочет это сделать. Вот эти методы:
1 2 3 4 5 6 |
public static Collection unmodifiableCollection(Collection<? extends T> c); public static Set unmodifiableSet(Set<? extends T> s); public static List unmodifiableList(List<? extends T> list); public static <K,V> Map<K, V> unmodifiableMap(Map<? extends K, ? extends V> m); public static SortedSet unmodifiableSortedSet(SortedSet<? extends T> s); public static <K,V> SortedMap<K, V> unmodifiableSortedMap(SortedMap<K, ? extends V> m); |
Какую же коллекцию выбрать?
Этим вопросом часто задаются программисты выбирая между множеством коллекций, представленных в Java Collections Framework. Ниже представлена таблица, в которой собраны все наиболее значимые характеристики коллекций:
Коллекция | Упорядо
чивание | Random Access | Ключ-значение | Дубликат Элементы | Нулевой элемент | Потоко
безопасность |
ArrayList | Да | Да | Нет | Да | Да | Нет |
LinkedList | Да | Нет | Нет | Да | Да | Нет |
HashSet | Нет | Нет | Нет | Нет | Да | Нет |
TreeSet | Да | Нет | Нет | Нет | Нет | Нет |
HashMap | Нет | Да | Да | Нет | Да | Нет |
TreeMap | Да | Да | Да | Нет | Нет | Нет |
Vector | Да | Да | Нет | Да | Да | Да |
Hashtable | Нет | Да | Да | Нет | Нет | Да |
Properties | Нет | Да | Да | Нет | Нет | Да |
Stack | Да | Нет | Нет | Да | Да | Да |
CopyOnWriteArrayList | Да | Да | Нет | Да | Да | Да |
ConcurrentHashMap | Нет | Да | Да | Нет | Нет | Да |
CopyOnWriteArraySet | Нет | Нет | Нет | Нет | Да | Да |
В этом обзоре мы узнали основные компоненты Java Collections Framework. В следующих статьях мы разберем популярные коллекции и научимся использовать каждую коллекцию по назначению.