JavaRush /Курси /Java Syntax Zero /Знайомство з колекцією HashMap

Знайомство з колекцією HashMap

Java Syntax Zero
Рівень 14 , Лекція 4
Відкрита

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 має такі методи:

Метод Опис
void put(ТКлюч key, ТЗначення value)
Додає в колекцію пару (key, value)
ТЗначення get(ТКлюч key)
Повертає значення відповідно до ключа.
boolean containsKey(ТКлюч key)
Перевіряє наявність ключа в колекції
boolean containsValue(ТЗначення value)
Перевіряє наявність значення в колекції
ТЗначення remove(ТКлюч key)
Видаляє елемент із колекції
void clear()
Очищає колекцію: видаляє всі елементи
int size()
Повертає кількість пар елементів у колекції
Set<ТКлюч> keySet()
Повертає множину ключів колекції
Collection<ТЗначення> values()
Повертає множину елементів колекції
Set<Map.Entry<TКлюч, TЗначення>> entrySet()
Повертає всі значення колекції у вигляді множини (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(), а як перебирати множини, ви вже знаєте:

Код Опис
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Сергій", 21);
map.put("Микола", 22);
map.put("Іван Петрович", 48);
map.put("Ганнуся", null);

for (String key: map.keySet())
{
   Integer value = map.get(key);
   System.out.println(key + " --> " + value);
}






Цикл за всіма ключами map

Отримуємо значення за ключем

Метод keySet() повертає множину ключів. Цю множину можна використати двома способами:

Короткий запис Довгий запис
for (String key: map.keySet())
{
   Integer value = map.get(key);
   System.out.println(key + " --> " + value);
}
Set<String> keys = map.keySet();

for (String key: keys)
{
   Integer value = map.get(key);
   System.out.println(key + " --> " + value);
}


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>
ArrayList<String> list = new ArrayList<String>();

list.add("Привіт");
list.add("Hello");

String s = list.get(0);
list.set(0, s + "!");

for (String item: list)
{
   System.out.println(item);
}
HashMap<Integer, String> map = new HashMap<Integer, String>();

map.put(0, "Привіт");
map.put(1, "Hello");

String s = map.get(0);
map.put(0, s + "!");

for (String item: map.values())
{
   System.out.println(item);
}

Коментарі (16)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Soros Рівень 25
27 серпня 2025
Методу void put(ТКлюч key, ТЗначення value) у класі HashMap немає! Існує метод V put(ТКлюч key, ТЗначення value) - тобто цей метод повертає або null в тому випадку, коли такого ключа ще не додавалось, або ТЗначення value, якщо така сама пара вже існує в HashMap об'єкті
Михайло Рівень 117
8 січня 2025
3 задача тупо копіпаста з лекції)
Кирило Рівень 43
19 липня 2024
Шось я завис на успішності студентів-2
Ivan Maksymovych Рівень 1 Expert
5 вересня 2023
в задачке Успішність студента 3 можно же решить все намного проще и легче, благодаря пройденным темам)

for (String names: grades.keySet()
             ) {
            System.out.println(names +" : "+grades.get(names) );

        }
Все выводится как нужно, но валидатор не пустит все равно)))
10 жовтня 2023
а можно и так:


for (var entry :
                grades.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
3 строки кода, море удовольствия!
2 липня 2023
А як створити об'єкт HashMap і одразу при ініціалізації додати до нього елементи(пари) без метода put?
Ihor Prokudin Рівень 51
22 березня 2023
Годину сидів і намагався зрозуміти про Set<Entry<>>, сходив по каву і до мене дійшло :/
Roma Chernesh Рівень 16
8 лютого 2023
Ото може в мене одного так, але щось тема із колекціями дуже важкой йде. Знаю, що початківцям зазвичай не вдається зрозуміти роботу подвійних (чи потрійних) масивів. Але якось ту тему вдалося пережувати і втянутися. А тут прям повна каша:(
[V.I.R.U.S.] Рівень 24 Expert
21 лютого 2023
Мужик. ти маєш зрозуміти що все геніальне просте. Не пошкодуй свій час і пройдись назад по темам масивів. Включай в Ютубі різних блогерів+ прочитай 2-3 статті на цю тему від різних авторів. І все стане на свої місця.
Roma Chernesh Рівень 16
22 лютого 2023
Та згоден! Ото який код не побачу по джуві - усюди ці колекції. Тому, каша-не каша, а розуміти треба!
Anonymous #696530 Рівень 19
28 вересня 2022
По класу Entry інтуїтивно зрозуміло, що воно все круто і зручно, але самостійно такими речами поки важко оперувати... особливо зі скороченнями.. По Задачі "Успішність студентів-3" скопіював код з лекції і адаптував за 2 хв, таке вже нормально виходить, не знаю добре це чи погано... ))
Andriy Рівень 20
10 серпня 2022
Задачу про перетворення ArrayList в HashMap можна вирішити не замінюючи ArrayList на HashMap, а циклом витягнути з нього індекси і значення, яким потім наповнити HashMap
Pavlo Kezin Рівень 23
12 вересня 2023
теж так робив, але спочатку зробив як у відповіді, але чомусь не пройшло. подумав це було обов"язково.
Lipovskyi Volodymyr Рівень 36
7 червня 2022
Задачка Успішність студентів 2. Не виконано всі вимоги, тому що використовував print замість println))) 25 спроб)))
Andriy Рівень 16
31 жовтня 2022
Не знаю чи поміняли завдяки тобі, але зараз про це вказано: • Метод printStudents має виводити імена та прізвища всіх студентів із колекції grades (кожну пару з нового рядка).