아이템 32. 비트필드(bit field)대신 EnumSet을 사용하라.
32. 비트필드(bit field)대신 EnumSet을 사용하라.
// 비트 필드 열거형 상수 - 안티패턴
public class Text {
public static final int STYLE_BOLD = 1 << 0; // 1
public static final int STYLE_ITALIC = 1 << 1; // 2
public static final int STYLE_UNDERLINE = 1 << 2; // 4
public static final int STYLE_STRIKETHROUGH = 1 << 3; // 8
// 이 메서드의 인자는 STYLE_상수를 비트별(bitwise) OR 한 값이거나 0.
public void applyStyles(int styles) { ... }
}
//use
public static void main(String[] args){
Text text = new Text();
// 비트 필드 이제는 피해야 하는 구현법
text.applyStyles(Text.STYLE_BOLD | Text.STYLE_ITALIC);
}
비트 필드는 출력한 결과값에 대해 이해 하기 어렵다는 단점이 존재한다.
EnumSet을 사용하자.
- 다른 Set구현들과 같은 수준의 상호운용성(interoperability)를 제공한다.
- enum값 갯수가 64이하인 경우, 내부적으로 비트 백터(bit vector)를 사용하기 때문에 데이터 저장 효율도 좋다.
- EnumSet은 long값 하나만 사용한다. 그렇기 때문에 비트 필드에 필적하는 성능이 나온다.
- removeAll이나 retainAll같은 일괄 연산(bulk operation)도 비트 단위 산술 연산을 통해 구현되어 있기 때문에 비트 필드와 같은 속도가 나온다.
public class Text{
public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }
public void applyStyles(Set<Style> styles) { ... }
}
//use
public static void main(String[] args){
Text text = new Text();
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
}
결론
- 열거형 자료 집합을 사용할 때는
EnumSet
을 사용하자. - 단점은 EnumSet이 불편타입이 아니라는 것인데,
Collections.unmodifiableSet
으로 포장하거나, Guava와 같은 라이브러리를 사용하면 된다.