1. 개요

EnumMap 은 Enum 을 키로 독점적으로 사용  하는  Map  구현입니다 .

이 사용방법(예제)에서는 속성, 일반적인 사용 사례 및 사용해야 하는 경우에 대해 설명합니다.

2. 프로젝트 설정

요일을 그날 하는 스포츠와 매핑해야 하는 간단한 요구 사항을 상상해 보십시오.

Monday     Soccer                         
Tuesday    Basketball                     
Wednesday  Hiking                         
Thursday   Karate

이를 위해 enum을 사용할 수 있습니다.

public enum DayOfWeek {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

우리가 곧 보게 될 것은 우리 Map의 핵심이 될 것입니다.

3. 창조

EnumMap 탐색을 시작하려면 먼저 인스턴스화해야 합니다.

EnumMap<DayOfWeek, String> activityMap = new EnumMap<>(DayOfWeek.class);
activityMap.put(DayOfWeek.MONDAY, "Soccer");

그리고 여기에 HashMap 과 같은 일반적인 것과의 첫 번째 차이점이 있습니다. HashMap 을 사용  하면 유형 매개변수화로 충분하므로  new 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<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 을 throw합니다 .

4. 요소 추가 및 검색

EnumMap 을 인스턴스화한 후  put() 메서드 를 사용하여 스포츠를 추가할 수 있습니다  .

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

그리고 그것을 검색하기 위해 get() 을 사용할 수 있습니다 :

assertThat(activityMap.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

이제  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. 요소 제거

특정 날짜의 매핑을 해제하려면 간단히  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개의 다른 뷰 또는 하위 컬렉션을 가질 수 있습니다.

먼저 활동에 대한 새 Map를 만들어 보겠습니다.

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() 입니다. 

Collection values = dayMap.values();
assertThat(values)
  .containsExactly("Soccer", "Hiking", "Karate");

여기서 EnumMap  은 순서가 지정된 맵입니다. DayOfWeek  열거형의 순서를 사용  하여 항목의 순서를 결정합니다.

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")
    );

Map에서 순서를 지정하는 것은 확실히 유용할 수 있으며 TreeMap을 HashMap과 비교 하는 사용방법(예제)에서 더 자세히 설명 합니다 .

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 어레이 에 의해 백업  되기만 하면 된다는 것을 의미합니다. 반면에 일반  Map  구현은 일반 객체를 키로 사용하는 것과 관련된 문제를 해결해야 합니다. 예를 들어,  HashMap  은 해시 충돌 가능성을 수용하기 위해 복잡한 데이터 구조와 훨씬 더 복잡한 저장 및 검색 논리 를 필요로 합니다.

8.2. 기능

또한 우리가 보았듯이 EnumMap  은 보기가 열거형 순서로 반복된다는 점에서 정렬된 맵입니다. 더 복잡한 시나리오에서 유사한 동작을 얻으려면  TreeMap 또는  LinkedHashMap 을 볼 수 있습니다 .

9. 결론

이 기사에서 우리는  Map  인터페이스 의 EnumMap  구현을 탐구했습니다. Enum  을 키로  사용할 때  EnumMap  이 유용할 수 있습니다.

이 예제에서 사용된 모든 예제의 전체 소스 코드는  GitHub 프로젝트 에서 찾을 수 있습니다 .

Generic footer banner