1. Обзор
EnumMap – это реализация Map |, которая исключительно использует Enum в качестве своих ключей.
В этом уроке мы обсудим его свойства, общие случаи использования и то, когда мы должны его использовать.
2. Настройка проекта
Представьте себе простое требование, когда нам нужно сопоставить дни недели со спортом, в который мы играем в этот день:
Monday Soccer Tuesday Basketball Wednesday Hiking Thursday Karate
Для этого мы могли бы использовать перечисление:
public enum DayOfWeek { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
Который, как мы скоро увидим, станет ключом к нашей карте.
3. Создание
Чтобы начать изучение EnumMap , сначала нам нужно создать один экземпляр:
EnumMapactivityMap = new EnumMap<>(DayOfWeek.class); activityMap.put(DayOfWeek.MONDAY, "Soccer");
И вот наше первое отличие от чего-то более распространенного, например HashMap . Обратите внимание , что для HashMap достаточно параметризации типа, что означает, что мы можем уйти с new HashMap<>(). Однако для EnumMap требуется тип ключа в конструкторе .
3.1. EnumMap Конструктор копирования
EnumMap также поставляется с двумя конструкторами копирования. Первый берет другой EnumMap :
EnumMapactivityMap = new EnumMap<>(DayOfWeek.class); activityMap.put(DayOfWeek.MONDAY, "Soccer"); activityMap.put(DayOfWeek.TUESDAY, "Basketball"); EnumMap activityMapCopy = new EnumMap<>(dayMap); assertThat(activityMapCopy.size()).isEqualTo(2); assertThat(activityMapCopy.get(DayOfWeek.MONDAY)).isEqualTo("Soccer"); assertThat(activityMapCopy.get(DayOfWeek.TUESDAY)).isEqualTo("Basketball");
3.2. Карта Конструктор копирования
Или, если у нас есть непустая Карта , ключ которой является перечислением, то мы тоже можем это сделать:
MapordinaryMap = new HashMap(); ordinaryMap.put(DayOfWeek.MONDAY, "Soccer"); EnumMap enumMap = new EnumMap(ordinaryMap); assertThat(enumMap.size()).isEqualTo(1); assertThat(enumMap.get(DayOfWeek.MONDAY)).isEqualTo("Soccer");
Обратите внимание, что карта должна быть непустой, чтобы EnumMap можно определить тип ключа по существующей записи.
Если указанная карта содержит более одного типа перечисления, конструктор выдаст ClassCastException .
4. Добавление и извлечение элементов
После создания экземпляра EnumMap мы можем добавить наш вид спорта с помощью метода put() :
activityMap.put(DayOfWeek.MONDAY, "Soccer");
И чтобы получить его, мы можем использовать get() :
assertThat(clubMap.get(DayOfWeek.MONDAY)).isEqualTo("Soccer");
5. Проверка элементов
Чтобы проверить, есть ли у нас отображение, определенное для определенного дня, мы используем containsKey() :
activityMap.put(DayOfWeek.WEDNESDAY, "Hiking"); assertThat(activityMap.containsKey(DayOfWeek.WEDNESDAY)).isTrue();
И, чтобы проверить, сопоставлен ли конкретный вид спорта с каким-либо ключом, мы используем containsValue() :
assertThat(activityMap.containsValue("Hiking")).isTrue();
5.1. значение null в качестве значения
Сейчас, нулевой является семантически допустимым значением для EnumMap .
Давайте свяжем null с “ничего не делать” и сопоставим его с субботой:
assertThat(activityMap.containsKey(DayOfWeek.SATURDAY)).isFalse(); assertThat(activityMap.containsValue(null)).isFalse(); activityMap.put(DayOfWeek.SATURDAY, null); assertThat(activityMap.containsKey(DayOfWeek.SATURDAY)).isTrue(); assertThat(activityMap.containsValue(null)).isTrue();
6. Удаление Элементов
Чтобы отменить сопоставление определенного дня, мы просто удаляем() его:
activityMap.put(DayOfWeek.MONDAY, "Soccer"); assertThat(activityMap.remove(DayOfWeek.MONDAY)).isEqualTo("Soccer"); assertThat(activityMap.containsKey(DayOfWeek.MONDAY)).isFalse();
Как мы можем наблюдать, удалить(ключ) возвращает предыдущее значение, связанное с ключом, или нулевой если не было никакого сопоставления для ключа.
Мы также можем выбрать отменить сопоставление определенного дня только в том случае, если этот день сопоставлен с определенной деятельностью:
activityMap.put(DayOfWeek.Monday, "Soccer"); assertThat(activityMap.remove(DayOfWeek.Monday, "Hiking")).isEqualTo(false); assertThat(activityMap.remove(DayOfWeek.Monday, "Soccer")).isEqualTo(true);
удалить(ключ, значение) удаляет запись для указанного ключа только в том случае, если ключ в данный момент сопоставлен с указанным значением.
7. Просмотры коллекций
Как и в случае с обычными картами, с любым EnumMap у нас может быть 3 разных представления или подколлекции.
Во-первых, давайте создадим новую карту нашей деятельности:
EnumMapactivityMap = new EnumMap(DayOfWeek.class); activityMap.put(DayOfWeek.THURSDAY, "Karate"); activityMap.put(DayOfWeek.WEDNESDAY, "Hiking"); activityMap.put(DayOfWeek.MONDAY, "Soccer");
7.1. ценности
Первое представление нашей карты активности-это values () , которая, как следует из названия, возвращает все значения на карте:
Collection values = dayMap.values(); assertThat(values) .containsExactly("Soccer", "Hiking", "Karate");
Обратите внимание, что EnumMap это упорядоченная карта. Он использует порядок День недели перечисление для определения порядка записей.
7.2. Набор ключей
Аналогично, keySet() возвращает коллекцию ключей, снова в порядке перечисления:
Set keys = dayMap.keySet(); assertThat(keys) .containsExactly(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.SATURDAY);
7.3. Вход
Наконец, entrySet() возвращает отображение в парах ключа и значения:
assertThat(dayMap.entrySet()) .containsExactly( new SimpleEntry(DayOfWeek.MONDAY, "Soccer"), new SimpleEntry(DayOfWeek.WEDNESDAY, "Hiking"), new SimpleEntry(DayOfWeek.THURSDAY, "Karate") );
Упорядочение на карте, безусловно, может пригодиться, и мы более подробно рассмотрим наш учебник, в котором сравнивается древовидная карта с хэш-картой .
7.4. Изменчивость
Теперь помните, что любые изменения, которые мы внесем в исходную карту активности, будут отражены в любом из ее представлений:
activityMap.put(DayOfWeek.TUESDAY, "Basketball"); assertThat(values) .containsExactly("Soccer", "Basketball", "Hiking", "Karate");
И наоборот; любые изменения, которые мы внесем в подвиды, будут отражены в исходной карте активности:
values.remove("Hiking"); assertThat(activityMap.containsKey(DayOfWeek.WEDNESDAY)).isFalse(); assertThat(activityMap.size()).isEqualTo(3);
Согласно контракту EnumMap с интерфейсом Map , вложенные представления поддерживаются исходной картой.
8. Когда использовать EnumMap
8.1. Производительность
Использование Enum в качестве ключа позволяет выполнить дополнительную оптимизацию производительности, например, более быстрое вычисление хэша, поскольку все возможные ключи известны заранее.
Простота наличия enum в качестве ключа означает, что EnumMap нужно только создать резервную копию простого старого Java Массива с очень простой логикой хранения и извлечения. С другой стороны, реализации generic Map должны учитывать проблемы, связанные с наличием общего объекта в качестве его ключа. Например, HashMap нуждается в сложной структуре данных и значительно более сложной логике хранения и извлечения для обеспечения возможности столкновения хэшей.
8.2. Функциональность
Кроме того, как мы видели, EnumMap является упорядоченной картой, поскольку ее представления будут повторяться в порядке перечисления. Чтобы получить аналогичное поведение для более сложных сценариев, мы можем посмотреть на TreeMap или LinkedHashMap .
9. Заключение
В этой статье мы рассмотрели реализацию EnumMap интерфейса Map . При работе с Enum в качестве ключа может пригодиться EnumMap .
Полный исходный код для всех примеров, используемых в этом руководстве, можно найти в проекте GitHub .