Введение в коллекции Java

Коллекция, как следует из названия, представляет собой группу объектов. Фреймворк Java Collections состоит из интерфейсов и классов, которые помогают работать с различными типами коллекций, такими как списки, наборы, карты, стеки и очереди и т. д.

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

1. Иерархия коллекций Java

Фреймворк Collections лучше понять с помощью основных интерфейсов. Классы коллекций реализуют эти интерфейсы и предоставляют конкретные функции.

Иерархия коллекций Java
Иерархия коллекций Java

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. Это делает код программиста красивым и чистым.

Код также легче читать благодаря единообразным названиям классов и методов.

6. Дальнейшее чтение

Прокрутить вверх