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