[Effective Java] Item37 - ordinal 인덱싱 대신 EnumMap을 사용하라

지구🌍·2023년 3월 12일
0

Effective Java 공부

목록 보기
10/12
post-thumbnail

ordinal 메소드가 무엇일까?

💡 해당 상수가 그 열거 타입에서 몇 번째 위치하는지 반환하는 메소드

예제코드

public class Snack {

    enum Type {
        BOX,
        BAG,
        BARREL
    }

    final String name;
    final Type type;

    Snack(String name, Type type) {
        this.name = name;
        this.type = type;
    }

    @Override
    public String toString() {
        return "Snack{" +
                "name='" + name + '\'' +
                '}';
    }
}

orinal 인덱싱

import java.util.HashSet;
import java.util.Set;

public class ShoppingBasket {

    public static void main(String[] args) {
        // 과자의 타입마다 분리하기 위해 Set 배열을 만들고, 초기 사이즈를 과자의 총 타입의 갯수로 지정한다.
        Set<Snack>[] snacksByType = (Set<Snack>[]) new Set[Snack.Type.values().length];

        //초기화
        for (int i = 0; i < snacksByType.length; i++) {
            snacksByType[i] = new HashSet<>();
        }

        // 장바구니에 과자를 담는다.
        Snack[] shoppingBasket = {
                new Snack("초코파이", Snack.Type.BOX),
                new Snack("양파링", Snack.Type.BAG),
                new Snack("바나나킥", Snack.Type.BAG),
                new Snack("후레치파이", Snack.Type.BOX),
                new Snack("새우깡", Snack.Type.BAG)
        };

        // 장바구니에 담은 과자들을 타입별로 분리한다.
        for (Snack snack : shoppingBasket) {
            snacksByType[snack.type.ordinal()].add(snack); // 이 때, ordinal()을 사용한다. (BOX = 0, BAG = 1)
        }

        // 결과를 출력한다.
        for (int i = 0; i < snacksByType.length; i++) {
            System.out.printf("%s: %s%n", Snack.Type.values()[i], snacksByType[i]);
        }
    }
}

문제점

  1. 배열은 제네릭과 호환되지 않기 때문에 비검사 형변환이 수행되고, 컴파일이 안된다.
  2. 초기화를 할 때, 정수 값을 잘못 입력하면 ArrayIndexOutOfBoundException이 발생한다.
  3. orinal()은 상수 선언 순서에 따라 변한다.

EnumMap

💡 enum map : Map 인터페이스에서 키를 특정 열거형 타입만을 사용하도록 하는 구현체

import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class ShoppingMap {

    public static void main(String[] args) {
        // 과자의 타입마다 분리하기 위해 EnumMa을 사용한다.
        Map<Snack.Type, Set<Snack>> snacksByType = new EnumMap<>(Snack.Type.class);

        // 초기화를 해준다.
        for (Snack.Type type : Snack.Type.values()) {
            snacksByType.put(type, new HashSet<>());
        }

        //장바구니에 과자를 담는다!
        Snack[] shoppingBasket = {
                new Snack("초코파이", Snack.Type.BOX),
                new Snack("양파링", Snack.Type.BAG),
                new Snack("바나나킥", Snack.Type.BAG),
                new Snack("후레치파이", Snack.Type.BOX),
                new Snack("새우깡", Snack.Type.BAG)
        };

        //장바구니에 담은 과자들을 타입별로 분리한다.
        for (Snack snack : shoppingBasket) {
            snacksByType.get(snack.type).add(snack);
        }

        //결과를 출력한다.
        System.out.println(snacksByType);
    }
}

장점

  1. 코드가 더 간결해지고 성능도 비슷하다.
  2. 배열 인덱스를 계산하는 과정에서 오류가 날 일이 없고, 타입에 안전하게 사용할 수 있다.
  3. 출력용 문자열을 제공해주어, 결과를 확인할 때 따로 formatting을 해주지 않아도 된다.

🎈귀중한 참고자료🎈
참고자료1

profile
일취월장 하며 성장! 중! 공부한 것을 기록하자(^∀^●)ノシ

0개의 댓글