Интерфейс 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 коллекции внутри

Search Icon

Довольно важно знать как Hash коллекции работают под капотом.

HashMap под капотом разбит на 16 linkedlist в которых собственно и хранятся пары. То есть сам HashMap это тоже массив из 16 ячеек, но каждая ячейка представляет собой отдельный LinkedList.

Добавление элемента в HashMap происходит так, что сначала по ключу вычисляется некий код, который называется hashcode, а по нему индекс нужного LinkedList-а в массиве из 16 LinkedList и в linkedlist-е с этим индексом сохраняется элемент.

При выборке из HashMap, например с помощью get, ранее вставленного элемента, будет происходить тот же процесс, что и при его вставке, то есть расчет hashcode по ключу, который был передан в get и собственно выборка из того linkedlist-а который соответствует рассчитанному hashcode.

Example

Например:

Очевидно, что и при вставке, например, ключа 10, и при выборке по этому ключу будет рассчитан один и тот же hashcode. Соответственно и вставка ключа 10 и выборка по ключу 10 будет происходить в одном и том же linkedlist-е.

Для ключа, например 13, вставка и выборка уже, возможно, попадет на другой linkedlist. А возможно попадет на тот linkedlist где перед перед этим вставилось 10. Зависит от рассчитанного hashcode для числа 13.

Отсюда очевиден смысл hashmap, что поскольку мы и вставляем и выбираем в одном и том же linkedlist-e, то выборка ясное дело всегда идет в одном из 16 linkedList-ов, а не во всех, и это ясное дело лучше, чем если бы мы вибирали из всех шестнадцати как в одном большом linkedlist-e.

Search Icon

Также важно упомянуть, что поиск нужного 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")); // По результатам можно видеть что элементы в порядке добавления } }

Вывод:

Интерфейс Set в Java

Изучите HashSet, TreeSet и LinkedHashSet в Java: как хранить только уникальные элементы, сортировать их и сохранять порядок вставки. Примеры кода.
Time to read: 9

Потоки ввода/вывода. PrintWriter и PrintStream

Разбираем PrintWriter и PrintStream в Java: в чем разница, когда использовать. Примеры вывода данных в консоль с помощью этих потоков.
Time to read: 10

FileStream в Java: чтение и запись файлов

FileInputStream и FileOutputStream в Java: как читать и записывать файлы побайтно. Пример преобразования строки в байты и обратно.
Time to read: 7