스터디/이펙티브 자바

[Effective Java] Item 37. ordinal 인덱싱 대신 EnumMap

📝 작성 : 2022.06.26  ⏱ 수정 : 
728x90

예제코드

public class Plant {

    enum LifeCycle { ANNUAL, PERNNIAL, BIENNIAL}

    final String name;
    final LifeCycle lifeCycle;

    public Plant(String name, LifeCycle lifeCycle) {
        this.name = name;
        this.lifeCycle = lifeCycle;
    }

    @Override
    public String toString() {
        return name;
    }
}

ordianl 인덱싱

Set<Plant>[] plantsByLifeCycle = (Set<Plant>[]) new Set[LifeCycle.values().length];
for (int i = 0 ; i < plantsByLifeCycle.length ; i++) {
    plantsByLifeCycle[i] = new HashSet<>();
}

for (Plant plant : garden) {
    plantsByLifeCycle[plant.lifeCycle.ordinal()].add(plant);
}

for (int i = 0 ; i < plantsByLifeCycle.length ; i++) {
    System.out.printf("%s : %s%n", LifeCycle.values()[i], plantsByLifeCycle[i]);
}

문제

  • 배배열은 제네릭과 호환되지 않아 비검사 형변환을 수행해야 함
  • 배열은 각 인덱스의 의미를 모르기 때문에 출력 결과에 직접 레이블을 달아야 함
  • 정수는 열거 타입과 달리 type-safe 하지 않기 때문에 정확한 정수값을 사용한다는 것을 직접 보증해야 함

EnumMap

Map<LifeCycle, Set<Plant>> plantsByLifeCycle = new EnumMap<>(LifeCycle.class);

for (LifeCycle lifeCycle : LifeCycle.values()) {
    plantsByLifeCycle.put(lifeCycle,new HashSet<>());
}

for (Plant plant : garden) {
    plantsByLifeCycle.get(plant.lifeCycle).add(plant);
}

//EnumMap은 toString을 재정의
System.out.println(plantsByLifeCycle);

장점

  • 형변환을 하지 않음
  • EnumMap의 toString을 이용하여 출력
  • ordinal을 이용해 배열 인덱스를 사용하지 않아 인덱스를 계산하는 과정에서 오류가 발생하지 않음
  • EnumMap은 내부에서 배열을 사용하기 때문에 Map의 타입 안전성과 배열의 성능을 보장
반응형