


1. Множество пар: ключ-значение.
В Java есть еще одна интересная коллекция (в широком смысле) — это коллекция Map
. Точного перевода ее названия на русский нет: чаще всего ее называют «карта», «словарь» или просто «мапа».
Эта коллекция похожа на коллекцию Set
, только хранит не множество элементов, а множество «пар элементов». Каждая пара элементов Map
состоит из двух: «ключ» и «значение».
Допустим, вы хотите хранить в программе имена сотрудников компании, их зарплаты или имена ваших коллег и их возраст. Тогда вам бы понадобилась таблица типа такой:
Имя | Возраст |
---|---|
Сергей | 21 |
Николай | 22 |
Иван Петрович | 48 |
Анюта | ? |
В каждой строке тут хранится пара величин. Имя мы будем называть ключом пары, а возраст — значением пары.
Весь набор таких пар и будет называться картой — Map
.
Ключом пары может быть что угодно, но у некоторых типов карт ключ не может быть null
. Ключи должны быть уникальные: одна карта не может содержать два одинаковых ключа.
2. Класс HashMap
Класс HashMap
является самой популярной коллекцией из всех карт (Map
). С одной стороны, он очень похож на HashSet и имеет все его методы, а с другой — на список (ArrayList
), если бы индексами у списка могли быть не числа, а слова.
Создать объект типа HashMap
можно с помощью команды вида:
HashMap<TКлюч, TЗначение> имя = new HashMap<TКлюч, TЗначение>();
Где TКлюч
— это тип ключей из пары элементов, TЗначение
— тип значений в паре элементов, которые будут храниться в коллекции HashMap
.
У класса HashMap
есть такие методы:
Метод | Описание |
---|---|
|
Добавляет в коллекцию пару (key , value ) |
|
Возвращает значение по ключу. |
|
Проверяет наличие ключа в коллекции |
|
Проверяет наличие значения в коллекции |
|
Удаляет элемент из коллекции |
|
Очищает коллекцию: удаляет все элементы |
|
Возвращает количество пар элементов в коллекции |
|
Возвращает множество ключей коллекции |
|
Возвращает множество элементов коллекции |
|
Возвращает все значения коллекции в виде множества (Set ) пар (Map.Entry ). |
Добавление элементов в HashMap
Элементы добавляются в карту сразу парами: для этого используется метод put()
. Первым в него передается ключ, вторым — значение.
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Серега", 21);
map.put("Николай", 22);
map.put("Иван Петрович", 48);
map.put("Анюта", null);
Если при добавлении элемента выяснится, что элемент с таким ключом уже есть, старое значение ключа заменится на новое.
Такое поведение делает HashMap
похожим на массив или список, если бы у них в качестве индексов выступали слова (String
), а не числа.
В качестве Типа-Ключа и Типа-Значения могут выступать практически любые типы. Есть небольшие дополнительные требования к Типу-Ключу, но о них вы узнаете при детальном изучении коллекций в квесте Java Collections.
3. Подмножества HashMap
: множество ключей
Допустим мы хотим просто вывести все элементы HashMap
на экран, как нам это сделать? Для этого нужно понять, как пройтись по всем элементам HashMap
. Это можно сделать разными способами.
Самый простой способ – использовать цикл по ключам
У элементов класса HashMap
нет порядкового номера, поэтому цикл со счетчиком тут не подойдет. Зато мы можем получить множество ключей с помощью метода keySet()
, а как пройтись по множеству вы уже знаете:
Код | Описание |
---|---|
|
Цикл по всем ключам map Получаем значение по ключу |
Метод keySet()
возвращает множество ключей. Можно использовать это множество двумя способами:
Компактная запись | Длинная запись |
---|---|
|
|
4. Использование цикла по парам
Есть и более сложный способ: можно преобразовать Map
в множество пар элементов, а потом использовать цикл по элементам множества, как мы уже раньше учили.
В коллекции HashMap
есть вспомогательный класс для хранения пары элементов. Выглядит он примерно так:
class Entry<KeyType, ValueType>
{
private KeyType key;
private ValueType value;
public KeyType getKey()
{
return this.key;
}
public ValueType getValue()
{
return this.value;
}
}
Результат вызова метода entrySet()
у объекта типа HashMap<ТКлюч, ТЗначение>
будет иметь тип Set<Entry<ТКлюч, ТЗначение>>
:
Set<Entry<Ключ, Значение>> имя = map.entrySet();
Тут мы видим сложный тип Set
с параметром-значением, а в качестве параметра-значение выступает еще один сложный тип (Entry
), так еще и с двумя параметрами.
Новичку очень легко в этом запутаться. Хотя, если разберетесь, сможете писать код вида:
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Серега", 21);
map.put("Николай", 22);
map.put("Иван Петрович", 48);
map.put("Анюта", null);
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for(Map.Entry<String, Integer> pair: entries)
{
String key = pair.getKey();
Integer value = pair.getValue();
System.out.println(key + " --> " + value);
}
Хотя этот код можно и немножко упростить:
Во-первых, можно не создавать отдельную переменную для entries
, а сразу вызвать метод entrySet()
внутри цикла for
:
for(Map.Entry<String, Integer> pair: map.entrySet())
{
String key = pair.getKey();
Integer value = pair.getValue();
System.out.println(key + " --> " + value);
}
Во-вторых, можно воспользоваться недавно появившимся оператором var
для автоматического выведения типа пары элементов:
for(var pair: map.entrySet())
{
String key = pair.getKey();
Integer value = pair.getValue();
System.out.println(key + " --> " + value);
}
Уже неплохо, да?
5. Сравнение ArrayList
vs HashMap
HashMap
сильно напоминает ArrayList
, у которого в качестве индексов используются не цифры, а слова (или другой тип ключей).
А если в качестве ключа в HashMap
использовать Integer
, он становится еще более похожим на ArrayList
. Сравните:
Код с ArrayList<String> | Код с HashMap<Integer, String> |
---|---|
|
|
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ