1. Множина пар: ключ–значення
>У Java є ще одна цікава колекція (в широкому сенсі) — це колекція Map
. Точного перекладу її назви немає: найчастіше її називають «карта», «словник» або просто «мапа» — саме цей термін ми й використовуватимемо надалі.
Ця колекція схожа на колекцію Set
, але зберігає не множину елементів, а множину «пар елементів». Кожна пара елементів Map
— це «ключ» і «значення».
Припустімо, ви хочете зберігати в програмі імена працівників компанії та їхні зарплати або імена своїх колег та їхній вік. Тоді вам знадобиться така таблиця:
Ім'я | Вік |
---|---|
Сергій | 21 |
Микола | 22 |
Іван Петрович | 48 |
Ганнуся | ? |
Тут у кожному рядку зберігається пара значень. Ім'я будемо називати ключем пари, а вік — значенням пари.
Увесь набір таких пар і буде називатися мапою — Map
.
Ключем пари може бути що завгодно, але у деяких типів мап ключ не може мати значення null
. Ключі мають бути унікальними: одна мапа не може містити два однакових ключі.
2. Клас HashMap
Клас HashMap
— це найпопулярніша колекція з усіх мап (Map
). З одного боку, він дуже схожий на HashSet і має всі його методи, а з іншого — на список (ArrayList
), якби індексами списку могли бути не числа, а слова.
Створити об'єкт типу HashMap
можна за допомогою такої команди:
HashMap<TКлюч, TЗначення> ім'я = new HashMap<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
і HashMap
HashMap
дуже нагадує ArrayList
, в якому індексами є не цифри, а слова (або інший тип ключів).
А якщо використовувати в HashMap
ключ типу Integer
, ця колекція стане ще більше схожою на ArrayList
. Порівняйте:
Код з ArrayList<String> | Код із HashMap<Integer, String> |
---|---|
|
|
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ