Map в Java с примерами

map in java

В статье о коллекциях я обещал написать статью о Map в Java. Сейчас мы подробно разберем эту очень полезную и нужную структуру данных с примерами кода.

Когда мы слышим слово мап, то первое, что приходит на ум — это карта (у меня гугл мапс). Map как структура данных не имеет ничего общего с картами гугла.

Чтобы правильно понять, что такое мап вспомните поликлинику. Да, воспоминания не очень. Но, нам нужно только вспомнить регистратуру, когда для приема у врача нам сначала нужно выстоять здоровенную очередь за своей картой. Не знаю как там в Европе, но для граждан стран СНГ это знакомо. Мы приходим, говорим свои данные и получаем карточку. Если же мы приходим впервые, нас регистрируют и только потом выдают карточку. Как правило карты находятся в алфавитном порядке и «милой» тете с регистратуры ее не сложно найти.

регистратура

Map в java — это структура данных, которая хранит данные в виде <Ключ, Значение>. Каждое значение можно найти по его ключу. Немного фактов о мап:

  • карта не может содержать дубликаты ключей;
  • каждый ключ может отображать только одно значение (далее мы посмотрим реализации map и что бывает, если попробовать добавить несколько объектов с одним ключом);
  • Map не расширяет интерфейс Collection.

Иерархия классов Map немного похожа на Set:

мап иерархия классов

Как видим у интерфейса мап есть несколько реализаций. Самые используемые и популярные это: HashMap<K, V>, TreeMap<K, V>. Их мы и рассмотрим подробнее.

HashMap — хранит ключи в hash-таблице. Она имеет наибольшую производительность. Однако такая реализация не гарантирует порядок элементов.

TreeMap — хранит ключи в отсортированном порядке. Работает медленнее чем хэшмап.

LinkedHashMap — хранит ключи в порядке их вставки в мап. Работает немного медленнее чем HashMap.

WeakHashMap — реализация интерфейса Map на основе хэш-таблицы со слабыми ключами. Запись в WeakHashMap будет автоматически удалена, если ее ключ больше не используется обычным образом.

Рассмотрим подробнее HashMap. Скорость ее работы О(1), а в худшем случае O(logn). Чтобы понять, когда будет худший случай давайте разберемся как она работает. Это, кстати, очень популярный вопрос на собеседованиях.

У каждого объекта есть метод hashCode, который возвращает значение хэш кода. Когда мы помещаем объект в HashMap сначала определяется значение hash кода его ключа, далее выбирается место, куда поместить объект в зависимости от полученного хэш кода. Если по такому ключу уже есть значение в мапе, то проверяется объект, который мы пытаемся добавить если он такой же как и существующий, то идет перезапись. Если объекты разные, а хэш код одинаковый (произошла коллизия или мы неправильно переопределили метод hashCode) объект помещается в ту самую ячейку в виде связанного списка. Вот откуда худший случай работы HashMap. Когда хэш код ключей одинаковый эта структура начинает работать как LinkedList скорость которого O(logn). Вы можете спросить: как нужно переопределить метод hashCode чтобы он возвращал одинаковое значение для всех объектов? Вот пример:

Код   
package com.javamaster;

public class MapExamples {
   
    private String name;
    private double sum;
   
    public MapExamples(String name, double sum) {
        this.name = name;
        this.sum = sum;
    }
   
   

    @Override
    public int hashCode() {
        return 1;
    }

    public static void main(String[] args) {
        MapExamples example1 = new MapExamples("Some name", 34);
        MapExamples example2 = new MapExamples("Another name", 12.5);
        System.out.println(example1.hashCode());
        System.out.println(example2.hashCode());
    }

}

Да, нужно постараться, чтобы такое сделать, но все же.

Теперь перейдем к примеру. Будут рассмотрены только самые популярные методы. Они у всех реализациях одинаковы.

Код   
package com.javamaster;

import java.util.HashMap;
import java.util.Map;

public class MapExamples {
   

    public static void main(String[] args) {
        Map<Integer, String> users = new HashMap<>();
        users.put(1, "Ivan");//добавление элементов
        users.put(2, "Nataliya");
        users.put(3, "Anton");
        System.out.println(users.get(2));//получение по ключу
       
        System.out.println(users.containsKey(1));//проверка есть значение с таким ключем
        users.remove(1);//удаление по ключу
        System.out.println(users.containsKey(1));
       
        System.out.println(users.size());//размер мапы
       
        System.out.println(users.isEmpty());//проверка пустая ли мапа
       
        users.forEach((k, v) -> System.out.println(k + ": " + v));//элегантный вывод
    }
}

результат работы хэш мап

Что еще хотелось бы упомянуть о Map в java:

  • желательно не использовать ключи, которые могут изменяться. Так можно потерять доступ к объекту;
  • желательно всегда переопределять методы equals и hashCode в объектов, которые вы будете сравнивать, помещать или извлекать с коллекции (не только мап);
  • две мапы равны если у них один и тот же набор пары ключ-значение.

Вот и все, что касается интерфейса Map и его реализации. Теперь у Вас будет полное представление о стандартных коллекциях в java и их применениях.

Понравилась статья? Поделиться с друзьями:
Комментарии: 3
  1. Orest Zaburelko

    А где HashTable?

  2. Виталик

    Очень сложнааааа

  3. Павел

    Слишком просто

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: