❐ Description
EnumMap에 대해서 자세히 알아보고 넘어가보자.
❐ Javadoc에 정의된 EnumMap
Javadoc-EnumMap을 보고 정리한 내용이다.
1. A specialized Map implementation for use with enum type keys.
Enum을 키로 쓸 수 있는 특수한 Map 구현체다.
EnumMap<RankCondition, Integer> rankTable = new EnumMap<>(RankCondition.class);
2. Enum maps are represented internally as arrays.
Enum Map은 내부적으로 배열을 사용해 매우 간결하고 효율적이다.
public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
implements java.io.Serializable, Cloneable
{
private transient Object[] vals;
}
내부 소스에서 확인할 수 있다.
참고로 transient 키워드는 직렬화 작업에서 제외된다.
3. Enum maps are maintained in the natural order of their keys.
키의 자연 순서(enum 상수 선언 순서)대로 유지됩니다.
public enum RankCondition {
NONE(0, (count, bonus) -> count == 6 && !bonus, ZERO),
FIFTH(3, (count, bonus) -> count == 3 && !bonus, FIFTH_RANK_PRIZE),
FOURTH(4, (count, bonus) -> count == 4 && !bonus, FOURTH_RANK_PRIZE),
THIRD(5, (count, bonus) -> count == 5 && !bonus, THIRD_RANK_PRIZE),
SECOND(5, (count, bonus) -> count == 5 && bonus, SECOND_RANK_PRIZE),
FIRST(6, (count, bonus) -> count == 6 && !bonus, FIRST_RANK_PRIZE);
//...
}
@Test
@DisplayName("Enum 상수를 정의해 놓은 순서대로 출력")
void enumConstantOrderTest() {
EnumMap<RankCondition, Integer> enumMap = new EnumMap<>(RankCondition.class);
RankCondition.sortedValuesExceptNone()
.forEach(rank -> enumMap.put(rank, 0));
enumMap.forEach((key, value) -> System.out.println(key));
}
위 테스트의 출력 결과는 RankCondition에 정의한 상수들의 순서대로 출력된다.
FIFTH
FOURTH
THIRD
SECOND
FIRST
4. Iterators returned by the collection views are weakly consistent:
약한 일관성을 가지고 있다.
약한 일관성을 가지고 있다라는 말은, iterator(반복자)가 반복 중에 EnumMap에 변경이 발생해도 즉시 오류가
발생하지 않으며, 변경 사항을 즉시 반영하지 않을 수 있다는 것을 뜻한다.
일반적으로 자바의 컬렉션 반복자는 “fail-fast” 특성을 가지고 있어서, 반복 중에 컬렉션이 수정되면 ConcurrentModificationException을 발생시키며, 이는 잘못된 상태의 데이터를 다루는 것을 방지해 준다.
그러나 EnumMap의 반복자는 약한 일관성을 가지기 때문에 이런 예외를 발생시키지 않는다.
대신 반복 중간에 발생한 변경 사항을 반영할 수도 있고, 반영하지 않을 수도 있다.
즉, 약한 일관성은 반복자가 컬렉션의 상태 변화를 즉각적으로 반영하지 않을 수도 있기 때문에 데이터가 일관되지
않을 가능성을 허용하는 것이다. 따라서 동시성 문제가 발생할 수 있으므로, EnumMap을 여러 스레드에서 사용할
경우 적절한 동기화 처리가 필요하다.
5. Null keys are not permitted.
Null 키는 허용되지 않는다.
Null 값을 삽입하려 하면 NPE가 발생한다.
단, Null 키의 존재 여부를 테스트하거나 제거하는 작업은 정상적으로 수행된다.
6.Like most collection implementations EnumMap is not synchronized
대부분의 컬렉션 구현체들과 마찬가지로 EnumMap은 동기화되지 않는다.
EnumMap은 동기화되지 않으므로, 여러 스레드가 동시에 접근할 경우 외부에서 동기화를 해야된다.
이를 위해 `Collections.synchronizedMap()` 메서드를 이용해 생성 시점에서 동기화하는 것이 좋다.
❐ EnumMap 성능이 일반 HashMap 보다 좋다고 평가되는 이유
EnumMap이 HashMap보다 성능이 더 좋은 이유는 EnumMap이 enum 타입에 키에 특화되어
매우 효율적인 내부 구조를 사용하기 때문이다.
1. 내부 구현의 배열 사용
EnumMap은 내부적으로 배열을 사용해 데이터를 저장한다. enum은 고정된 상수 집합이기 때문에,
EnumMap은 enum의 각 상수를 배열의 인덱스처럼 사용하여 매핑할 수 있다.
예를 들어, 특정 enum 타입이 3개의 상수를 가지고 있다면, EnumMap은 크기 3의 배열을 생성해 각 상수에
대응하는 값을 저장한다. 이 방식 덕분에 해시 함수를 계산하거나 버킷을 관리하는 추가 작업이 필요하지 않으므로
매우 빠른 조회와 저장 성능을 발휘할 수 있다.
2. Hash 계산이 필요 없음
HashMap은 키의 해시 값을 계산하여 저장 위치를 결정하는데, 이 과정에서 추가적인 계산과
메모리 접근이 필요하다. 반면, EnumMap은 배열의 인덱스를 사용하므로 해시 계산 과정이 생략됩니다.
이로 인해 키를 찾거나 값을 삽입할 때 성능 오버헤드가 적어진다.
3. 공간 효율성
HashMap은 동적으로 크기를 조절해야 하기 때문에 버킷의 개수를 증가시키면서 해시 충돌을 최소화하려 한다.
이에 비해 EnumMap은 enum 타입의 모든 상수에 대해 고정 크기의 배열을 사용해 미리 할당하므로,
필요한 메모리 양이 예측 가능하고 공간 낭비가 적다. 특히 enum 상수 개수가 적은 경우 EnumMap은 매우 적은
메모리로도 충분히 동작할 수 있다.
4. 자연 순위 유지
EnumMap은 키의 순서를 enum 상수 선언 순서대로 유지한다. 이로 인해 정렬된 데이터 조회가 필요한 경우
TreeMap 같은 구조를 사용하지 않아도 되므로 성능적으로 유리하다. 반면 HashMap은 해시 값을 기반으로
저장하기 때문에 데이터 순서가 보장되지 않는다.
'우테코 7기 > 3주차' 카테고리의 다른 글
과제를 하면서 알게된 사소한 지식들 (0) | 2024.11.04 |
---|---|
정적 팩토리 메소드 왜 쓰는걸까? (0) | 2024.11.04 |
Map의 computeXxx 메소드를 알아보자. (0) | 2024.11.03 |
3주차 회고 (0) | 2024.11.03 |
로또 (0) | 2024.11.03 |