Бесплатный курс по Java: от основ до продвинутого уровня
Интерфейс Map в Java
Благодаря классам реализующим Map можно создать массив из пар ключ-значение. То есть один элемент этого массива это пара.
Пример программы:
import java.util.*;
public class Map {
public static void main(String[] args) {
//создаем коллекцию
HashMap< Integer, String > hMap = new HashMap< Integer, String >();
//добавление элемента
//видим числовой ключ и соответствующее ему значение
hMap.put(34, “Sunday”);
hMap.put(56, “Monday”);
hMap.put(85, “Tuesday”);
hMap.put(34, “Wednesday”);
hMap.put(556, “Monday”);
hMap.put(724, “Sunday”);
// удаление элемента
hMap.remove(85);
//В hashset нету get по индексу и не наследует iterator
//поэтому передаем значения с помощью метода values
//в конструктор другой коллекции, которую можно перебирать.
ArrayList< String > hMapValues = new ArrayList< String >(hMap.values());
for(int i = 0; i < hMapValues.size(); i++) {
System.out.print(hMapValues.get(i) + " ");
}
System.out.println();
//или keySet если нужно перебирать ключи
ArrayList< Integer > hMapKeys = new ArrayList< Integer >(hMap.keySet());
for(int i = 0; i < hMapKeys.size(); i++) {
System.out.print(hMapKeys.get(i) + " ");
}
System.out.println();
// проверка на наличие элемента с таким ключем в списке
System.out.println(hMap.containsKey(56));
// проверка на наличие элемента с таким значением в списке
System.out.println(hMap.containsValue("Sunday"));
// можно также получить значение элемента hashmap по ключу
System.out.println(hMap.get(34));
}
}
Вывод:
Hash коллекции внутри
Довольно важно знать как Hash коллекции работают под капотом.
HashMap под капотом разбит на 16 linkedlist в которых собственно и хранятся пары. То есть сам HashMap это тоже массив из 16 ячеек, но каждая ячейка представляет собой отдельный LinkedList.
Добавление элемента в HashMap происходит так, что сначала по ключу вычисляется некий код, который называется hashcode, а по нему индекс нужного LinkedList-а в массиве из 16 LinkedList и в linkedlist-е с этим индексом сохраняется элемент.
При выборке из HashMap, например с помощью get, ранее вставленного элемента, будет происходить тот же процесс, что и при его вставке, то есть расчет hashcode по ключу, который был передан в get и собственно выборка из того linkedlist-а который соответствует рассчитанному hashcode.
Например:
Очевидно, что и при вставке, например, ключа 10, и при выборке по этому ключу будет рассчитан один и тот же hashcode. Соответственно и вставка ключа 10 и выборка по ключу 10 будет происходить в одном и том же linkedlist-е.
Для ключа, например 13, вставка и выборка уже, возможно, попадет на другой linkedlist. А возможно попадет на тот linkedlist где перед перед этим вставилось 10. Зависит от рассчитанного hashcode для числа 13.
Отсюда очевиден смысл hashmap, что поскольку мы и вставляем и выбираем в одном и том же linkedlist-e, то выборка ясное дело всегда идет в одном из 16 linkedList-ов, а не во всех, и это ясное дело лучше, чем если бы мы вибирали из всех шестнадцати как в одном большом linkedlist-e.
Также важно упомянуть, что поиск нужного linkedlist-a из 16 по hashcode происходит за константное время, проще говоря скорость лучше не бывает.
TreeMap
TreeMap – хранит пары в виде дерева, что позволяет быстрее искать элементы.
Все элементы отсортированы по ключу.
TreeMap лучше всего подходит для нахождения диапазонов
Пример программы:
import java.util.*;
public class Map {
public static void main(String[] args) {
// создаем коллекцию
TreeMap< Integer, String > tMap = new TreeMap< Integer, String >();
// добавление элемента
tMap.put(556, “Monday”);
tMap.put(56, “Monday”);
tMap.put(85, “Tuesday”);
tMap.put(34, “Wednesday”);
tMap.put(815, “Saturday”);
tMap.put(724, “Sunday”);
// удаление элемента
tMap.remove(85);
// в TreeMap нету get по индексу и не наследует iterator
// поэтому передаем значения с помощью метода values
// конструктор другой коллекции, которую можно перебирать
ArrayList< String > tMapValues = new ArrayList< String >(tMap.values());
for(int i = 0; i < tMapValues.size(); i++) {
System.out.print(tMapValues.get(i) + " ");
}
System.out.println();
// или keySet если нужно перебирать ключи
ArrayList< Integer > tMapKeys = new ArrayList< Integer >(tMap.keySet());
for(int i = 0; i < tMapKeys.size(); i++) {
System.out.print(tMapKeys.get(i) + " ");
}
System.out.println();
// проверка на наличие элемента с таким ключем в списке
System.out.println(tMap.containsKey(56));
// проверка на наличие элемента с таким значением в списке
System.out.println(tMap.containsValue("Sunday"));
// для нахождения диапазонов
System.out.println(tMap.tailMap(556)); // выведет все элементы после 556
System.out.println(tMap.headMap(815)); // выведет все элементы до 815
// по результатам можно увидеть что элементы в порядке увеличения
}
}
Вывод:
LinkedHashMap
LinkedHashMap – элементы в отличие от hashmap содержат ссылку на предыдущий добавленный элементы и на следующий добавленный, как у LinkedList.
Проще говоря, это гибрид HashMap и LinkedList.
То есть лучше использовать когда элементы часто вставляются/удаляются.
Пример программы:
import java.util.*;
public class Map {
public static void main(String[] args) {
// создаем коллекцию
LinkedHashMap< Integer, String > lhMap = new LinkedHashMap< Integer, String >();
// добавление элемента
lhMap.put(556, “Monday”);
lhMap.put(556, “Monday”);
lhMap.put(85, “Tuesday”);
lhMap.put(34, “Wednesday”);
lhMap.put(815, “Saturday”);
lhMap.put(724, “Sunday”);
// удаление элемента
lhMap.remove(85);
//в linkedhashset нету get по индексу и не наследует iterator
//поэтому передаем значения с помощью метода values
//в конструктор другой коллекции, которую можно перебрать
ArrayList< String > lhMapValues = new ArrayList< String >(lhMap.values());
for(int i = 0; i < lhMapValues.size(); i++) {
System.out.print(lhMapValues.get(i)+" ");
}
System.out.println();
//или keySet если нужно перебрать ключи
ArrayList< Integer > lhMapKeys = new ArrayList< Integer >(lhMap.keySet());
for(int i = 0; i < lhMapKeys.size(); i++) {
System.out.print(lhMapKeys.get(i)+" ");
}
System.out.println();
// проверка на наличие элемента с таким ключем в списке
System.out.println(lhMap.containsKey(556));
// проверка на наличие элемента с таким значением в списке
System.out.println(lhMap.containsValue("Sunday"));
// По результатам можно видеть что элементы в порядке добавления
}
}