1. Вступ
У реальному житті ми часто стикаємося із ситуаціями, коли кожному унікальному «ключу» потрібно зіставити певне «значення». Телефонна книга зберігає номер телефону та імʼя людини, словник пов’язує слово з його перекладом, а в таблиці оцінок у кожного студента є власне імʼя та відповідний бал.
У Java для таких завдань є інтерфейс Map. Це колекція, що зберігає пари «ключ — значення» (key-value pair).
Головні властивості Map:
- Кожен ключ унікальний (дублікати не допускаються).
- Одному ключу може відповідати лише одне значення.
- Значення можуть повторюватися.
Уявімо аналогію. Якщо список (List) — це як черга в їдальні (кожен стоїть на своїй позиції, можна звернутися за номером), то відображення (Map) — це ніби шафка з комірками: кожна комірка має номер (ключ) і в ній лежить щось своє (значення).
Інтерфейс Map: базові операції
Інтерфейс Map оголошує основні методи для роботи з парами ключ-значення:
| Метод | Опис |
|---|---|
|
Додати або замінити значення за ключем |
|
Отримати значення за ключем |
|
Видалити пару за ключем |
|
Перевірити, чи є такий ключ |
|
Перевірити, чи є таке значення |
|
Кількість пар у відображенні |
|
Перевірити, чи порожня мапа |
|
Видалити всі пари |
Типи K і V — це параметри типу (generics): K (Key) — тип ключа, V (Value) — тип значення.
3. Клас HashMap: швидкий доступ за ключем
Що таке HashMap?
HashMap — найпопулярніша реалізація інтерфейсу Map. Вона забезпечує швидкий доступ до значень за ключем.
Важливо: HashMap не гарантує порядок зберігання елементів! Якщо ви додали ключі у певному порядку, під час перебирання вони можуть іти в іншому.
Як створити HashMap?
import java.util.HashMap;
import java.util.Map;
public class Example {
public static void main(String[] args) {
// Створюємо мапу: ключ — String, значення — Integer
Map<String, Integer> ages = new HashMap<>();
// Додаємо елементи
ages.put("Василь", 25);
ages.put("Петро", 30);
ages.put("Марія", 22);
// Отримуємо значення за ключем
int vasyaAge = ages.get("Василь");
System.out.println("Вік Василя: " + vasyaAge); // 25
// Перевіряємо наявність ключа
if (ages.containsKey("Марія")) {
System.out.println("Марія є у списку!");
}
// Видаляємо елемент
ages.remove("Петро");
// Перебираємо всі пари ключ-значення
for (String name : ages.keySet()) {
System.out.println(name + ": " + ages.get(name));
}
}
}
Виведення:
Вік Василя: 25
Марія є у списку!
Василь: 25
Марія: 22
Особливості HashMap
Головне, що варто пам’ятати: ключі в HashMap завжди унікальні. Якщо ви додасте новий елемент із уже наявним ключем, старе значення буде замінено новим.
Значення можуть повторюватися: кілька різних ключів можуть вказувати на одне й те саме значення.
І ще важливий момент — порядок елементів. HashMap не дбає про порядок додавання. Під час виведення записи можуть бути перемішані — це нормальна поведінка.
4. Клас TreeMap: сортування за ключем
На відміну від HashMap, клас TreeMap зберігає елементи у відсортованому порядку за ключем.
Коли використовувати TreeMap?
Коли важливо, щоб елементи йшли у зростаючому (або спадному) порядку ключів. Наприклад, якщо ви хочете вивести телефонну книгу за абеткою.
Приклад:
import java.util.Map;
import java.util.TreeMap;
public class TreeMapExample {
public static void main(String[] args) {
Map<String, String> phoneBook = new TreeMap<>();
phoneBook.put("Василь", "+1-900-123-45-67");
phoneBook.put("Марія", "+1-900-555-55-55");
phoneBook.put("Петро", "+1-900-222-33-44");
for (String name : phoneBook.keySet()) {
System.out.println(name + ": " + phoneBook.get(name));
}
}
}
Виведення:
Марія: +1-900-555-55-55
Петро: +1-900-222-33-44
Василь: +1-900-123-45-67
Зверніть увагу: ключі відсортовані за абеткою.
5. Основні операції з Map
Додавання та заміна елементів
Map<String, Integer> scores = new HashMap<>();
scores.put("Анна", 90);
scores.put("Іван", 85);
scores.put("Анна", 95); // Перезапише значення для "Анна"
Отримання значення
Integer annaScore = scores.get("Анна"); // 95
Integer unknown = scores.get("Василь"); // null, якщо такого ключа немає
Перевірка наявності ключа або значення
scores.containsKey("Іван"); // true
scores.containsValue(85); // true
Видалення пари за ключем
scores.remove("Іван");
Розмір мапи та очищення
int size = scores.size();
scores.clear(); // Видаляє всі елементи
5. Перебирання елементів Map
Map — це не список, індексів тут немає. Проте можна ітеруватися:
За ключами:
for (String key : scores.keySet()) {
System.out.println("Ключ: " + key + ", Значення: " + scores.get(key));
}
За значеннями:
for (Integer value : scores.values()) {
System.out.println("Значення: " + value);
}
За парами ключ — значення (найкращий спосіб):
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + " => " + value);
}
Коли використовувати HashMap, а коли — TreeMap?
HashMap — універсальний варіант «за замовчуванням». Якщо порядок ключів неважливий і головне — швидкість операцій, майже завжди беруть саме його.
TreeMap стане у пригоді, якщо потрібен порядок. Він автоматично зберігає ключі відсортованими та дозволяє швидко знаходити мінімальний і максимальний ключ або працювати з діапазонами.
Підсумок: у 90 % випадків беремо HashMap. Коли дані мають бути одразу «в порядку», використовуємо TreeMap.
6. Приклади використання Map
Приклад 1: Телефонна книга
Map<String, String> phoneBook = new HashMap<>();
phoneBook.put("Катя", "+1-999-111-22-33");
phoneBook.put("Олег", "+1-999-222-33-44");
phoneBook.put("Катя", "+1-999-555-66-77"); // Старий номер Каті буде замінено новим
for (Map.Entry<String, String> entry : phoneBook.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
Виведення:
Олег: +1-999-222-33-44
Катя: +1-999-555-66-77
Приклад 2: Підрахунок кількості слів
Припустімо, у нас є список слів, і ми хочемо дізнатися, скільки разів кожне слово трапляється:
import java.util.*;
public class WordCount {
public static void main(String[] args) {
List<String> words = Arrays.asList("яблуко", "банан", "яблуко", "груша", "банан", "яблуко");
Map<String, Integer> counts = new HashMap<>();
for (String word : words) {
int oldCount = counts.getOrDefault(word, 0); // якщо ключа немає — 0
counts.put(word, oldCount + 1);
}
System.out.println(counts); // {груша=1, яблуко=3, банан=2}
}
}
7. Типові помилки під час роботи з Map
Помилка № 1: Плутанина між ключами та значеннями. Новачки часто намагаються отримати значення за індексом, як у списку, або забувають, що ключі мають бути унікальними. У Map немає індексів — лише ключі.
Помилка № 2: Використання ключів і значень null. У HashMap дозволений ключ null, але в TreeMap — ні (буде NullPointerException). Значення можуть бути null в обох реалізаціях, але це рідко буває корисним.
Помилка № 3: Очікування порядку елементів у HashMap. HashMap не гарантує жодного порядку. Якщо потрібен порядок — використовуйте LinkedHashMap (зберігає порядок додавання) або TreeMap (сортує за ключем).
Помилка № 4: Модифікація Map під час ітерації. Якщо ви в циклі ітеруєте Map і водночас додаєте або видаляєте елементи — може виникнути ConcurrentModificationException. Для таких завдань використовуйте ітератор із методом remove() або спеціальні колекції.
Помилка № 5: Порівняння ключів і значень за == замість equals. Map використовує метод equals для порівняння ключів (і значень). Якщо ви створюєте власні класи-ключі, обов’язково перевизначайте equals і hashCode.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ