EnumMap指南

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 ,首先我們需要實例化一個:

EnumMap<DayOfWeek, String> activityMap = new EnumMap<>(DayOfWeek.class);

 activityMap.put(DayOfWeek.MONDAY, "Soccer");

這是我們與更常見的東西(例如HashMap )的第一個區別。注意,使用HashMap ,類型參數化就足夠了,這意味著我們可以使用新的HashMap <>()。**但是, EnumMap需要構造函數中的鍵類型**。

3.1。 EnumMap複製構造函數

EnumMap還附帶了兩個副本構造函數。第一個使用另一個EnumMap

EnumMap<DayOfWeek, String> activityMap = new EnumMap<>(DayOfWeek.class);

 activityMap.put(DayOfWeek.MONDAY, "Soccer");

 activityMap.put(DayOfWeek.TUESDAY, "Basketball");



 EnumMap<DayOfWeek, String> 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。Map複製構造函數

或者,如果我們有一個鍵為枚舉的非空Map ,那麼我們也可以這樣做:

Map<DayOfWeek, String> ordinaryMap = 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空

現在, nullEnumMap的語義有效值。

讓我們將null與“無所事事”相關聯,然後將其映射到Saturday:

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.移除元素

為了取消特定日期的映射,我們只需其remove() :

activityMap.put(DayOfWeek.MONDAY, "Soccer");

 assertThat(activityMap.remove(DayOfWeek.MONDAY)).isEqualTo("Soccer");

 assertThat(activityMap.containsKey(DayOfWeek.MONDAY)).isFalse();

如我們所見,remove(key)返回與該鍵關聯的先前值;如果沒有該鍵的映射,則返回null

我們還可以選擇**取消映射特定日期的特定日期:**

activityMap.put(DayOfWeek.Monday, "Soccer");

 assertThat(activityMap.remove(DayOfWeek.Monday, "Hiking")).isEqualTo(false);

 assertThat(activityMap.remove(DayOfWeek.Monday, "Soccer")).isEqualTo(true);

僅當鍵當前映射到指定值時,remove(key,value)才刪除指定鍵的條目。

7.集合視圖

就像普通地圖一樣,使用任何EnumMap ,我們可以擁有3個不同的視圖或子集合。

首先,讓我們為我們的活動創建一個新的地圖:

EnumMap<DayOfWeek, String> activityMap = new EnumMap(DayOfWeek.class);

 activityMap.put(DayOfWeek.THURSDAY, "Karate");

 activityMap.put(DayOfWeek.WEDNESDAY, "Hiking");

 activityMap.put(DayOfWeek.MONDAY, "Soccer");

7.1。values

我們的活動地圖的第一個視圖是*values()* ,顧名思義,它返回地圖中的所有值:

Collection values = dayMap.values();

 assertThat(values)

 .containsExactly("Soccer", "Hiking", "Karate");

請注意,此處的EnumMap是有序地圖。它使用DayOfWeek枚舉的順序來確定條目的順序。

7.2。keySet

類似地, *keySet()*再次以枚舉順序返回鍵的集合:

Set keys = dayMap.keySet();

 assertThat(keys)

 .containsExactly(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.SATURDAY);

7.3。 entrySet

最後, *entrySet()*以鍵和值對的形式返回映射:

assertThat(dayMap.entrySet())

 .containsExactly(

 new SimpleEntry(DayOfWeek.MONDAY, "Soccer"),

 new SimpleEntry(DayOfWeek.WEDNESDAY, "Hiking"),

 new SimpleEntry(DayOfWeek.THURSDAY, "Karate")

 );

地圖中的排序當然可以派上用場,並且我們在將TreeMap與HashMap進行比較的教程中進行了更深入的介紹。

7.4。可變性

現在,請記住,我們對原始活動map所做的任何更改都將反映在其任何視圖中:

activityMap.put(DayOfWeek.TUESDAY, "Basketball");

 assertThat(values)

 .containsExactly("Soccer", "Basketball", "Hiking", "Karate");

反之亦然;我們對子視圖所做的任何更改都將反映在原始活動map中:

values.remove("Hiking");

 assertThat(activityMap.containsKey(DayOfWeek.WEDNESDAY)).isFalse();

 assertThat(activityMap.size()).isEqualTo(3);

根據EnumMapMap接口的合同,子視圖由原始地圖支持。

8.何時使用EnumMap

8.1。性能

使用Enum作為鍵可以進行一些額外的性能優化,例如更快的哈希計算,因為所有可能的鍵都是預先知道的。

枚舉作為鍵的簡單性意味著EnumMap只需要由一個普通的Java Array進行備份,該Java Array具有非常簡單的存儲和檢索邏輯。另一方面,通用Map實現需要解決與將通用對像作為其鍵有關的問題。例如, HashMap需要復雜的數據結構以及相當複雜的存儲和檢索邏輯,以解決哈希衝突的可能性。

8.2。功能性

同樣,如我們所見, EnumMap是一個有序映射,因為它的視圖將以枚舉順序進行迭代。為了在更複雜的場景中獲得類似的行為,我們可以查看TreeMapLinkedHashMap

9.結論

在本文中,我們探討了Map接口的EnumMap實現。當使用Enum作為鍵時, EnumMap會派上用場。

本教程中使用的所有示例的完整源代碼都可以在GitHub項目中找到。