Ма

Мапи у Java

11 вправ

Про концепцію Мапи

Мапа - це структура даних для зберігання пар ключ-значення. Вона подібна до словників в інших мовах програмування. Інтерфейс Map визначає операції, які можна виконувати з мапою.

HashMap

У Java є чимало різних реалізацій Map. HashMap - одна з найпоширеніших.

// Make an instance
Map<String, Integer> fruitPrices = new HashMap<>();
Note

Коли ми оголошуємо змінну Map, краще вказувати тип Map, а не конкретний тип, як у прикладі вище. Так згодом легше змінити реалізацію Map.

HashMap також має конструктор копіювання.

// Make a copy of a map
Map<String, Integer> copy = new HashMap<>(fruitPrices);

Щоб додати записи до мапи, скористаймося put.

fruitPrices.put("apple", 100);
fruitPrices.put("pear", 80);
// => { "apple" => 100, "pear" => 80 }

З кожним ключем може бути повʼязане лише одне значення. Якщо викликати put із тим самим ключем, значення цього ключа оновиться.

fruitPrices.put("pear", 40);
// => { "apple" => 100, "pear" => 40 }

Щоб отримати значення для ключа, скористаймося get.

fruitPrices.get("apple"); // => 100

Щоб перевірити, чи містить мапа певний ключ, скористаймося containsKey.

fruitPrices.containsKey("apple");   // => true
fruitPrices.containsKey("orange");  // => false

Щоб видалити записи, скористаймося remove.

fruitPrices.put("plum", 90);  // Add plum to map
fruitPrices.remove("plum");   // Removes plum from map

Метод size повертає кількість записів.

fruitPrices.size();  // Returns 2

Методи keySet і values дають змогу отримати ключі або значення мапи як Set чи колекцію відповідно.

fruitPrices.keySet();  // Returns "apple" and "pear" in a set
fruitPrices.values();  // Returns 100 and 80, in a Collection

HashMap використовує hashCode та equals

HashMap використовує методи hashCode та equals обʼєкта, щоб визначити, де зберігати значення для ключа і як їх діставати. Тому важливо, щоб їхні повернені значення не змінювалися між збереженням і отриманням, інакше HashMap може не знайти значення.

Наприклад, припустімо, у нас є такий клас, який буде використовуватися як ключ мапи:

public class Stock {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (Objects.equals(Stock.class, obj.getClass()) && obj instanceof Stock other) {
            return Objects.equals(name, other.name);
        }
        return false;
    }
}

Методи hashCode та equals залежать від поля name, яке можна змінити через setName. Зміна hashCode може дати несподівані результати:

Stock stock = new Stock();
stock.setName("Beanies");

Map<Stock, Integer> stockCount = new HashMap<>();
stockCount.put(stock, 80);

stockCount.get(stock); // Returns 80

Stock other = new Stock();
other.setName("Beanies");

stockCount.get(other); // Returns 80 because "other" and "stock" are equal

stock.setName("Choccies");
stockCount.get(stock); // Returns null because hashCode value has changed

stockCount.get(other);  // Also returns null because "other" and "stock" are not equal

stock.setName("Beanies");
stockCount.get(stock); // HashCode restored, so returns 80 again

stockCount.get(other); // Also returns 80 again because "other" and "stock" are back to equal

Map.of і Map.copyOf

Ще один поширений спосіб створити мапу - скористатися Map.of або Map.ofEntries.

// Using Map.of
Map<String, Integer> temperatures = Map.of("Mon", 30, "Tue", 28, "Wed", 32);

// or using Map.ofEntries
Map<String, Integer> temperatures2 = Map.ofEntries(
    Map.entry("Mon", 30),
    Map.entry("Tue", 28),
    Map.entry("Wed", 32)
);

На відміну від HashMap, вони заповнюють мапу одразу й після створення стають доступними лише для читання. Map.copyOf створює копію мапи, доступну лише для читання.

Map<String, Integer> readOnlyFruitPrices = Map.copyOf(fruitPrices);

Виклик таких методів, як put, remove чи clear, призводить до UnsupportedOperationException.

Редагувати через GitHub Посилання відкривається в новому вікні або вкладці

Вивчити концепцію Мапи

Практика заблокована

Розблокуйте ще 1 вправу, щоб практикувати концепцію Мапи