Map и асоциативни колекции

Интерфейс Map и асоциативни колекции

Map е интерфейс от Java Collections Framework, предназначен за съхраняване на асоциативни двойки ключ–стойност (key–value). Всеки ключ в картата е уникален и служи за достъп до съответната стойност.

За разлика от интерфейсите List, Set и Queue, които съхраняват отделни елементи, Map работи с двойки ключ–стойност.

Основни характеристики на колекции от тип Map:

  • съхранява данни като асоциации (двойки ключ-стойност)
  • всеки ключ е уникален за дадената колекция
  • стойностите от своя страна могат да се повтарят
  • няма индекси
  • предоставят бързо търсене по ключ
  • един ключ може да бъде свързан само с една стойност (при повторно добавяне старата стойност се заменя).

Като пример за подобен тип структура могат да бъдат разгледани речник (дума - определение), телефонен указател (име - номер) и други подобни:

Map<String, String> phoneBook = new HashMap<>();

phoneBook.put("Ivan", "0888123456");
phoneBook.put("Maria", "0888987654");
phoneBook.put("Georgi", "0888456789");

System.out.println(phoneBook);

В примера всеки ключ представлява име на човек, а съответната стойност – негов телефонен номер:

{Ivan=0888123456, Georgi=0888456789, Maria=0888987654}

Map не наследява Collection

Причината е, че Collection работи с единични елементи, докато Map работи с двойки ключ–стойност и затова образува отделна йерархия.

Методи за работа с Map

Основни операции

put()
get()
remove()
containsKey()
containsValue()
Map<String, Integer> grades = new HashMap<>();

grades.put("Ivan", 6);
grades.put("Maria", 5);

System.out.println(grades.get("Ivan"));

System.out.println(grades.containsKey("Maria"));

grades.remove("Maria");

System.out.println(grades);

Методът put() добавя нова двойка ключ–стойност, get() извлича стойността по ключ, containsKey() проверява дали съществува даден ключ, а remove() премахва съответната двойка.

Map<String, Integer> grades = new HashMap<>();

grades.put("Ivan", 5);
grades.put("Ivan", 6);

Тъй като ключовете трябва да бъдат уникални, второто извикване на put() не добавя нов елемент, а заменя стойността на съществуващия ключ.

Операции, носещи информация за колекцията

size()
isEmpty()

Операции, използвани при обхождане

keySet()
values()
entrySet()

Основни имплементации на Map

Имплементация Подредба Очаквана сложност за get/put Особености
HashMap не гарантира ред O(1) средно използва хеширане
LinkedHashMap ред на добавяне O(1) средно запазва реда на обхождане
TreeMap сортирани ключове O(log n) използва балансирано дърво

Обхождане на Map

Методът entrySet() връща множество от двойки ключ-стойност. Той е подходящ при обхождане, когато са необходими и ключът, и стойността. Методът keySet() връща само ключовете, а стойността може да бъде получена допълнително чрез get(key).

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

public class Faculty {

    // pair specialty - number of students
    private Map<String, Integer> specialities = new HashMap<>();

    public String pairsToString() {
        StringBuilder result = new StringBuilder();

        for (Map.Entry<String, Integer> pair : specialities.entrySet()) {
            result.append(pair.getKey())
                  .append(" ")
                  .append(pair.getValue())
                  .append("\n");
        }
        return result.toString();
    }

    public String keysToString() {
        StringBuilder result = new StringBuilder();

        for (String key : specialities.keySet()) {
            result.append(key).append("\n");
        }
        return result.toString();
    }

    public String valuesToString() {
        StringBuilder result = new StringBuilder();

        for (Integer value : specialities.values()) {
            result.append(value).append("\n");
        }
        return result.toString();
    }
}

Сортиране на Map

Тъй като Map не е линейна структура, сортирането може да бъде направено или по ключ, или по стойност:

Подреждане по ключ

// за целта обекта, използван за ключ, трябва да имплементира Comparable
    public Map<String, Integer> sortByKey() {
        return new TreeMap<>(specialities);
    }

Подреждане по стойност

    public void sortByValue() {
        List<Map.Entry<String, Integer>> specialtyList = new ArrayList<>(specialities.entrySet());
        specialtyList.sort(Map.Entry.comparingByValue()); // при сложен обект, може да се дефинира Comparator
    }

This site uses Just the Docs, a documentation theme for Jekyll.