здрасти В този урок ще направим по-подробен преглед на Java HashMap . Преди това проучихме структури от данни, където елементите се съхраняват като себе си. В масив or ArrayList / LinkedList съхраняваме известен брой елементи. Но Howво ще стане, ако нашата задача се промени малко?
HashMap: Howъв вид карта е това?  - 1
Представете си следната задача: създайте списък от 100 души, който съхранява името и номера на паспорта на всеки човек. По принцип това не е толкова трудно. Например, можете да поставите и двете в низ и след това да създадете списък от тези низове: „Амелия Агилар, 4211 717171“. Но това решение има два недостатъка. Първо, може да се нуждаем от възможност за търсене по номер на паспорт. И това ще бъде проблематично предвид този формат за съхранение на информация. Второ, нищо не ни пречи да създадем двама различни хора с един и същи номер на паспорт. И това е най-сериозният недостатък на нашето решение. Това никога не трябва да се допуска: няма двама души с еднакъв номер на паспорт. На помощ ни идва нова структура от данни: Карта. Известен е също като "асоциативен масив", но този термин се използва рядко. По-често се нарича "речник" or "карта". :) Как е фундаментално различен от структурите от данни, които разгледахме преди? Преди всичко във факта, че данните в картата се съхраняват като двойки ключ-стойност. Всичко може да служи като ключове и стойности: числа, низове or обекти от други класове. Днес ще проучим най-често срещаната реализация на класа Map : Java HashMap . HashMap: Howъв вид карта е това?  - 2

И така, Howво трябва да знаем за HashMap в Java?

Създаването е много лесно:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();
}
Тук създаваме речник, който съхранява елементи като двойки "число-низ". Числото ще действа като ключ, а низът като стойност. Също така указваме типа ключ (Integer) и типа стойност (String). Защо? Първо, ключът HashMap винаги е уникален. Това ни устройва напълно, тъй като можем да използваме номера на паспорта като ключ и да избегнем дубликати. Стойността ще бъде низ с пълното име (различни хора могат да имат едно и също име; това не е повод за притеснение). Добавянето на нова двойка към HashMap изглежда така:

public class Main {

   public static void main(String[] args) {
       HashMap<Integer, String> passportsAndNames = new HashMap<>();

       passportsAndNames.put (212133, "Bridget Logan");
       passportsAndNames.put (162348, "Ivan the Great");
       passportsAndNames.put(8082771, "Donald John Trump");
       System.out.println(passportsAndNames);
   }
}
Използваме метода put() за това. Освен това HashMap заменя метода toString() , така че може да се показва на конзолата. Резултатът ще изглежда така: {212133=Бриджит Логан, 8082771=Доналд Джон Тръмп, 162348=Ivan Велики} Сега нека проверим дали ключовете наистина са уникални? Нека опитаме да добавим нов елемент с ключ , който вече е бил използван в картата:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");
   passportsAndNames.put(162348, "Albert Kent");// This key has already been used
   System.out.println(passportsAndNames);
}
Изход: {212133=Бриджит Логан, 8082771=Доналд Джон Тръмп, 162348=Албърт Кент} Както можете да видите, предишната стойност, свързана с ключа 162348 , беше презаписана. Използваме термина „ключ“ с причина. Стойностите в HashMap са достъпни с помощта на ключа, но не и обратното. Ключът не може да бъде получен с помощта на стойност, тъй като стойностите може да не са уникални. Това може да се види ясно при получаване or премахване на елемент от HashMap :

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   String lidiaName = passportsAndNames.get(212133);
   System.out.println(lidiaName);

   passportsAndNames.remove(162348);
   System.out.println(passportsAndNames);
}
За да получим стойност or да премахнем двойка от речника, трябва да предадем на get() и remove() уникалния ключ, който съответства на стойността. За разлика от масивите и списъците, HashMap в Java няма числови индекси: достъпът до стойностите се осъществява чрез ключа. Конзолен изход: Bridget Logan {212133=Bridget Logan, 8082771=Donald John Trump} Класовете ArrayList и LinkedList ни позволяват да проверим дали списъкът съдържа конкретен елемент. Java HashMap ни позволява да направим това. Нещо повече, можем да направим това и за двата члена на двойката: Това е, което съдържаКлюч () (проверява за ключ) и съдържаСтойност()(проверява за стойност) методите са за.

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   System.out.println(passportsAndNames.containsKey(11111));
   System.out.println(passportsAndNames.containsValue("Donald John Trump"));
}
Изход: false true Друга удобна функция на HashMap в Java е фактът, че можете да получите отделни списъци с всички ключове и всички стойности. Това се постига с методите keySet() и values() :

public class Main {

   public static void main(String[] args) {
       HashMap<Integer, String> passportsAndNames = new HashMap<>();

       passportsAndNames.put (212133, "Bridget Logan");
       passportsAndNames.put (162348, "Ivan the Great");
       passportsAndNames.put(8082771, "Donald John Trump");

       Set keys = passportsAndNames.keySet();
       System.out.println("Keys: " + keys);

       ArrayList<String> values = new ArrayList<>(passportsAndNames.values());
       System.out.println("Values: " + values);
   }
}
Ключовете се извличат в набор , който все още не сме разгледали. Той е специален с това, че не може да съдържа повтарящи се елементи. Сега основното нещо е да запомните, че списъкът с всички ключове може да бъде извлечен от HashMap в отделна колекция. В примера записахме стойностите в обикновен ArrayList . Конзолен изход: Ключове: [212133, 8082771, 162348] Стойности: [Бриджит Логан, Доналд Джон Тръмп, Ivan Велики] Методите size () и clear() правят точно същото като в предишните структури, които обсъдихме: първият връща броя на елементите в момента в речника, вторият премахва всички елементи.

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   System.out.println(passportsAndNames.size());
   passportsAndNames.clear();
   System.out.println(passportsAndNames);
}
Изход: 3 {} За да проверим дали има поне един елемент в нашия HashMap , можем да използваме метода isEmpty() :

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   if (!passportsAndNames.isEmpty()) {

       System.out.println(passportsAndNames);
   }
}
Изход: {212133=Бриджит Логан, 8082771=Доналд Джон Тръмп, 162348=Ivan Велики} Сега ще извеждаме към конзолата само след предварителна проверка. :) Друг интересен момент е, че две карти могат да се комбинират в една. Това се постига с помощта на метода putAll() . Извикваме го на първия HashMap , подаваме втория като аргумент и елементите от втория се добавят към първия:

public static void main(String[] args) {
   HashMap<Integer, String> passportsAndNames = new HashMap<>();
   HashMap<Integer, String> passportsAndNames2 = new HashMap<>();

   passportsAndNames.put (212133, "Bridget Logan");
   passportsAndNames.put (162348, "Ivan the Great");
   passportsAndNames.put(8082771, "Donald John Trump");

   passportsAndNames2.put(917352, "Clifford Patrick");
   passportsAndNames2.put(925648, "Mitchell Salgado");

   passportsAndNames.putAll(passportsAndNames2);
   System.out.println(passportsAndNames);
}
Изход: {917352=Клифърд Патрик, 212133=Бриджит Логан, 8082771=Доналд Джон Тръмп, 925648=Мичъл Салгадо, 162348=Ivan Велики} Всички двойки в passportsAndNames2 са копирани в passportsAndNames . Сега разгледайте един по-сложен пример. По-конкретно, итерация върху HashMap в цикъл.

for (Map.Entry<Integer, String> entry: passportsAndNames.entrySet()) {
   System.out.println(entry);
}
Класът Map.Entry обозначава двойката ключ-стойност в речника. Методът entrySet () връща списък на всички двойки в нашия HashMap . Тъй като нашата карта се състои от тези двойки Map.Entry , ние итерираме върху двойки, а не отделни ключове or стойности. Изход: 212133=Бриджит Логан 8082771=Доналд Джон Тръмп 162348=Ivan Велики Също така, не забравяйте да проучите официалната documentация на Oracle за HashMap .