Словари (также называемые картами и отображениями) позволяют сопоставить с определенным ключом некоторое значение. В языке Java для определения базового функционала словарей имеется интерфейс
Map<K, V>. Он представляет структуру данных, где каждый элемент представляет пару "ключ-значение". При этом в рамках объекта Map
все ключи уникальные. Такие коллекции облегчают поиск элемента, если нам известен ключ - уникальный идентификатор объекта.
Следует отметить, что в отличие от других интерфейсов, которые представляют коллекции, интерфейс Map НЕ расширяет интерфейс Collection.
Среди методов интерфейса Map можно выделить следующие:
void clear(): очищает коллекцию
boolean containsKey(Object k): возвращает true, если коллекция содержит ключ k
boolean containsValue(Object v): возвращает true, если коллекция содержит значение v
Set<Map.Entry<K, V>> entrySet(): возвращает набор элементов коллекции. Все элементы представляют объект Map.Entry
boolean equals(Object obj): возвращает true, если коллекция идентична коллекции, передаваемой через параметр obj
boolean isEmpty(): возвращает true, если коллекция пуста
V get(Object k): возвращает значение объекта, ключ которого равен k. Если такого элемента не окажется, то возвращается значение null
V getOrDefault(Object k, V defaultValue): возвращает значение объекта, ключ которого равен k. Если такого элемента не окажется,
то возвращается значение defaultVlue
V put(K k, V v): помещает в коллекцию новый объект с ключом k и значением v. Если в коллекции уже есть объект с подобным ключом,
то он перезаписывается. После добавления возвращает предыдущее значение для ключа k, если он уже был в коллекции. Если же ключа еще не было в коллекции,
то возвращается значение null
V putIfAbsent(K k, V v): помещает в коллекцию новый объект с ключом k и значением v, если в коллекции еще нет элемента с подобным ключом.
Set<K> keySet(): возвращает набор всех ключей словаря
Collection<V> values(): возвращает набор всех значений словаря
void putAll(Map<? extends K, ? extends V> map): добавляет в коллекцию все объекты из словаря map
V remove(Object k): удаляет объект с ключом k
boolean remove(Object k, Object v): удаляет объект с ключом k, если только его значение равно v
V replace(K k, V v): заменяет значение для указанного ключа k на v
boolean replace(K key, V oldValue, V newValue): заменяет значение для указанного ключа key на newValue, если только старое значение равно oldValue
int size(): возвращает количество элементов коллекции
static <K,V> Map<K,V> ofEntries(Map.Entry<? extends K, ? extends V>... entries): возвращает неизменяемые словарь, который содержит элементы из entries
Чтобы положить объект в коллекцию, используется метод put, а чтобы получить по ключу - метод get. Реализация интерфейса
Map также позволяет получить наборы как ключей, так и значений. А метод entrySet() возвращает набор всех элементов в виде объектов
Map.Entry<K, V>.
Обобщенный интерфейс Map.Entry<K, V> представляет объект с ключом типа K и значением типа V и определяет следующие методы:
boolean equals(Object obj): возвращает true, если объект obj, представляющий интерфейс Map.Entry, идентичен текущему
K getKey(): возвращает ключ объекта словаря
V getValue(): возвращает значение объекта словаря
V setValue(V v): устанавливает для текущего объекта значение v
int hashCode(): возвращает хеш-код данного объекта
При переборе объектов словаря мы будем оперировать этими методами для работы с ключами и значениями объектов.
Например, создадим неизменяемый словарь:
import java.util.Map;
public class Program{
public static void main(String[] args) {
Map<Integer,String> map = Map.ofEntries(
Map.entry(1, "Tom"),
Map.entry(2, "Bob"),
Map.entry(3, "Sam")
);
System.out.println(map); // {3=Sam, 2=Bob, 1=Tom}
}
}
В данном случае создается словарь, где ключи представляют тип Integer, а значения - тип String. Для создания словаря применяется мтеод Map.ofEntries(),
в который передаются объекты Map.Entry, создаваемые с помощью метода Map.entry(). Первый параметр этого метода - ключ, а второй - сопоставляемое с ним значение.
Например, выражение
Map.entry(1, "Tom")
Создает объект Map.Entry, где ключ - число 1, а значение - строка "Tom".
Поскольку результатом метода является неизменяемый словарь типа java.util.ImmutableCollections$MapN, то мы не можем изменять его значения. Но посмотрим, какие другие операции мы можем произвести со словарем.
import java.util.Map;
public class Program{
public static void main(String[] args) {
Map<Integer,String> map = Map.ofEntries(
Map.entry(1, "Tom"),
Map.entry(2, "Bob"),
Map.entry(3, "Sam")
);
// получаем размер словаряя
System.out.println(map.size()); // 3
// получаем все ключи
System.out.println(map.keySet()); // [3, 2, 1]
// получаем все значения
System.out.println(map.values()); // [Sam, Bob, Tom]
// получаем значение по ключу 2 из словаря
String item2 = map.get(2);
System.out.println("Item 2: " + item2); // Item 2: Bob
// перебор словаря
for(Map.Entry<Integer,String> item : map.entrySet()){
// получаем ключ
Integer key = item.getKey();
// получаем значение
String value = item.getValue();
System.out.printf("{ %d : %s}\n", key, value);
}
}
}
Базовым классом для всех словарей является абстрактный класс AbstractMap,
который реализует большую часть методов интерфейса Map. Наиболее распространенным классом словарей является HashMap,
который наследуется от класса AbstractMap и представляет реализацию интерфейса Map на основе хеш-таблицы.
Для создания словаря HashMap применяется ряд конструкторов:
HashMap(): создает пустойHashMapс начальной емкостью по умолчанию (16) и коэффициентом загрузки по умолчанию (0,75)
HashMap(int initialCapacity): создает пустойHashMapс указанной начальной ёмкостью и коэффициентом загрузки по умолчанию (0,75)
HashMap(int initialCapacity, float loadFactor): создает пустойHashMapс указанной начальной емкостью и коэффициентом загрузки
HashMap(Map<? extends K, ? extends V> m): создает новыйHashMapс теми же сопоставлениями, что и у заданного Map
Создание HashMap и добавление в него элементов:
import java.util.Map;
import java.util.HashMap;
public class Program{
public static void main(String[] args) {
// пустой словарь
var dict = new HashMap<String,String>();
// добавляем в него элементы
dict.put("red", "красный");
dict.put("green", "зеленый");
dict.put("blue", "синий");
System.out.println(dict); // {red=красный, green=зеленый, blue=синий}
Map<String,String> map = Map.ofEntries(
Map.entry("yellow", "желтый"),
Map.entry("brown", "коричневый")
);
// добавляем другой словарь с данными
dict.putAll(map);
System.out.println(dict); // {red=красный, green=зеленый, blue=синий, yellow=желтый, brown=коричневый}
}
}
В данном случае создаем словарь, где и ключи, и значения представляют строки. Затем с помощью методов put()/putAll() добавляем ряд объектов.
ПРимер получения данных из словаря:
import java.util.Map;
import java.util.HashMap;
public class Program{
public static void main(String[] args) {
Map<String,String> map = Map.ofEntries(
Map.entry("red", "красный"),
Map.entry("green", "зеленый"),
Map.entry("blue", "синий"),
Map.entry("yellow", "желтый")
);
var dict = new HashMap<String,String>(map);
System.out.println(dict); // {red=красный, yellow=желтый, green=зеленый, blue=синий}
// получаем размер словаряя
System.out.println(dict.size()); // 4
// получаем все ключи
System.out.println(dict.keySet()); // [red, yellow, green, blue]
// получаем все значения
System.out.println(dict.values()); // [красный, желтый, зеленый, синий]
// получаем значение по ключу "red" из словаря
String red = dict.get("red");
System.out.println("red: " + red); // red: красный
// проверяем наличие слова в словаре
var hasBlack = dict.containsKey("black");
System.out.println("black: " + (hasBlack ? dict.get("black"):" отсутствует")); // black: отсутствует
// перебор словаря
for(var word : dict.entrySet()){
// получаем ключ
var source = word.getKey();
// получаем значение
var translation = word.getValue();
System.out.printf("%s : %s\n", source, translation);
}
}
}
Пример изменения и удаления элементов словаря:
import java.util.Map;
import java.util.HashMap;
public class Program{
public static void main(String[] args) {
Map<String,String> map = Map.ofEntries(
Map.entry("red", "красный"),
Map.entry("green", "зеленый"),
Map.entry("blue", "синий"),
Map.entry("yellow", "желтый")
);
var dict = new HashMap<String,String>(map);
System.out.println(dict); // {red=красный, green=зеленый, blue=синий, yellow=желтый}
// меняем по ключу "red" значение на "червонный"
dict.replace("red", "червонный");
System.out.println(dict); // {red=червонный, green=зеленый, blue=синий, yellow=желтый}
// меняем по ключу "red" значение на "алый", только если значение "красный"
dict.replace("red", "алый", "красный");
// удаляем yellow
dict.remove("yellow");
System.out.println(dict); // {red=червонный, green=зеленый, blue=синий}
// удаляем все элементы
dict.clear();
System.out.println(dict); // {}
}
}
Чтобы добавить или заменить элемент, используется метод put, либо replace, а чтобы получить его значение по ключу - метод get. С помощью других методов интерфейса Map также производятся другие манипуляции над элементами: перебор, получение ключей, значений, удаление.