Коллекция, как следует из названия, представляет собой группу объектов. Фреймворк Java Collections состоит из интерфейсов и классов, которые помогают работать с различными типами коллекций, такими как списки, наборы, карты, стеки и очереди и т. д.
Эти готовые к использованию классы коллекций решают множество общих проблем, где нам нужно иметь дело с группами однородных и неоднородных объектов. Обычные операции включают добавление, удаление, обновление, сортировку, поиск и более сложные алгоритмы. Эти классы коллекций обеспечивают очень прозрачную поддержку для всех таких операций с использованием API коллекций.
1. Иерархия коллекций Java
Фреймворк Collections лучше понять с помощью основных интерфейсов. Классы коллекций реализуют эти интерфейсы и предоставляют конкретные функции.

1.1.Сбор
Интерфейс Collection находится в корне иерархии. Интерфейс Collection предоставляет все методы общего назначения, которые должны поддерживать все классы коллекций(или выдавать исключение UnsupportedOperationException). Он расширяет интерфейс Iterable, который добавляет поддержку итерации по элементам коллекции с использованием оператора « for-each loop ».
Все остальные интерфейсы и классы коллекций(кроме Map) либо расширяют, либо реализуют этот интерфейс. Например, интерфейсы List(индексированный, упорядоченный) и Set(сортированный) реализуют эту коллекцию.
1.2 Список
Списки представляют собой упорядоченную коллекцию элементов. Используя списки, мы можем получить доступ к элементам по их целочисленному индексу(позиции в списке) и искать элементы в списке. Индекс начинается с 0, как и массив.
Некоторые полезные классы, реализующие интерфейс List: ArrayList, CopyOnWriteArrayList, LinkedList, Stack и Vector.
1.3.Набор
Sets представляют собой коллекцию уникальных элементов. Sets не допускают дублирования элементов. Интерфейс Set не гарантирует возврат элементов в каком-либо предсказуемом порядке; хотя некоторые реализации Set хранят элементы в их естественном порядке и гарантируют этот порядок.
Некоторые полезные классы, реализующие интерфейс Set: ConcurrentSkipListSet, CopyOnWriteArraySet, EnumSet, HashSet, LinkedHashSet и TreeSet.
1.4 Карта
Интерфейс Map позволяет нам хранить данные в парах ключ-значение(ключи должны быть неизменяемыми). Map не может содержать дубликаты ключей; каждый ключ может соответствовать максимум одному значению.
Интерфейс Map предоставляет три представления коллекций, которые позволяют просматривать содержимое карты как набор ключей, набор значений или набор сопоставлений ключ-значение. Некоторые реализации карт, такие как класс TreeMap, дают определенные гарантии относительно их порядка; другие, такие как класс HashMap, этого не делают.
Некоторые полезные классы, реализующие интерфейс Map: ConcurrentHashMap, ConcurrentSkipListMap, EnumMap, HashMap, Hashtable, IdentityHashMap, LinkedHashMap, Properties, TreeMap и WeakHashMap.
1.5.Стек
Интерфейс Java Stack представляет собой классическую структуру данных стека, где элементы могут быть помещены в стек объектов LIFO(last-in-first-out). В Stack мы помещаем элемент на вершину стека и позже снова выталкиваем его с вершины стека.
1.6 Очередь
Структура данных очереди предназначена для хранения элементов(помещенных потоками-производителями) до обработки потоками-потребителями. Помимо основных операций по сбору, очереди предоставляют дополнительные операции вставки, извлечения и проверки.
Очереди обычно, но не обязательно, упорядочивают элементы в порядке FIFO(первым пришел — первым ушел). Одним из таких исключений является приоритетная очередь, которая упорядочивает элементы в соответствии с предоставленным Comparator или естественным порядком элементов.
В общем случае очереди не поддерживают блокирующие операции вставки или извлечения. Классы реализации блокирующих очередей реализуют интерфейс BlockingQueue.
Некоторые полезные классы, реализующие интерфейс Queue: ArrayBlockingQueue, ArrayDeque, ConcurrentLinkedDeque, ConcurrentLinkedQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, LinkedList, LinkedTransferQueue, PriorityBlockingQueue, PriorityQueue и SynchronousQueue.
1.7.Дек
Двусторонняя очередь(произносится как «дек»), которая поддерживает вставку и удаление элементов на обоих концах. Когда дек используется как очередь, возникает поведение FIFO(первым пришел — первым ушел). Когда дек используется как стек, возникает поведение LIFO(последним пришел — первым ушел).
Этот интерфейс следует использовать вместо устаревшего класса Stack. Когда deque используется как стек, элементы вставляются и выталкиваются из начала deque.
Некоторые общеизвестные классы, реализующие этот интерфейс: ArrayDeque, ConcurrentLinkedDeque, LinkedBlockingDeque и LinkedList.
2. Коллекции и дженерики Java
По своему назначению дженерики обеспечивают безопасность типов. Они обнаруживают несовместимые типы(в аргументах методов) и предотвращают ClassCastException во время выполнения. Мы также можем определить класс коллекции в коллекциях Java для хранения только определенного типа объекта. Все остальные типы должны быть запрещены. Это делается с помощью дженериков.
Первые два метода add() разрешены в данном примере. Третий не скомпилируется и выдаст ошибку – «Метод put(Integer, String) в типе HashMap<Integer,String> не применим для аргументов(String, String)». Это помогает обнаружить несовместимые типы на ранней стадии, чтобы предотвратить непредсказуемое поведение во время выполнения.
Generic HashMapHashMap<Integer, String> map = new HashMap<>();map.put(1, "A"); //allowedmap.put(2, "B"); //allowedmap.put("3", "C"); //NOT allowed - Key is string
3. Методы equals() и hashCode()
Многие классы коллекций предоставляют определенные функции, такие как сортировка элементов, отсутствие дубликатов элементов и т. д. Для реализации этого поведения добавленные элементы(объекты) должны правильно реализовывать методы equals() и hashCode().
Все классы-обертки Java и класс String переопределяют эти функции своей конкретной реализацией, поэтому они ведут себя правильно в таких коллекциях. Нам также нужно убедиться, что эти функции переопределяются правильно в наших пользовательских классах.
SortedSet<Integer> sortedSet = new TreeSet<>();sortedSet.add(2);sortedSet.add(1);sortedSet.add(1);sortedSet.add(3);System.out.println(sortedSet); //[1,2,3]
4. Изменения Java 8
Java 8 был основным релизом, который представил лямбда-стиль программирования в Java. В результате были также улучшены классы коллекций. Например, мы можем перебирать коллекции в одной строке и выполнять действие над всеми элементами коллекции с помощью оператора forEach.
ArrayList<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.forEach(System.out::print);
5. Преимущества коллекций Java
5.1. Последовательные и повторно используемые API
Это то, что делает фреймворк. Он предоставляет последовательный набор методов класса, которые можно использовать для решения похожего набора проблем снова и снова, не получая непредсказуемых результатов. Фреймворк коллекций Java также последовательно помогает решать общие проблемы, связанные с группой объектов.
Все классы коллекций имеют согласованную реализацию и предоставляют некоторые общие методы, такие как добавление, получение, размещение, удаление и т. д. Независимо от того, с какой структурой данных вы имеете дело, эти методы работают в соответствии с базовой реализацией и выполняют действия прозрачно.
5.2 Меньше времени на разработку
Общий и предсказуемый фреймворк всегда сокращает время разработки и помогает в написании прикладных программ в ускоренном режиме. Коллекция Java также помогает в выполнении некоторых наиболее повторяющихся общих задач с объектами и коллекциями и, таким образом, улучшает фактор времени.
5.3.Производительность
API-интерфейсы Java-коллекции написаны некоторыми из самых блестящих умов в отрасли, и их производительность является первоклассной в большинстве сценариев. Текущая работа по разработке Oracle и очень восторженное сообщество разработчиков Java помогают сделать его лучше.
5.4 Чистый код
Эти API были написаны с использованием всех хороших практик кодирования и очень хорошо документированы. Они следуют определенному стандарту во всей структуре коллекций Java. Это делает код программиста красивым и чистым.
Код также легче читать благодаря единообразным названиям классов и методов.