열거한 값들이 주로 집합으로 사용될 경우, 예전에는 각 상수에 서로 다른 2의 거듭제곱 값을 할당한 정수 열거 패턴(아이템 34)을 사용해 왔다.
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
// 매개변수 styles는 0개 이상의 STYLE_ 상수를 비트별 OR한 값이다.
public void applyStyles(int styles) { ... }
}
다음과 같은 식으로 비트별 OR를 사용해 여러 상수를 하나의 집합으로 모을 수 있는데, 이렇게 만들어진 집합을 비트 필드라한다.
text.applyStyles(STYLE_BOLD | STYLE_ITALIC);
비트 필드를 사용하면 비트별 연산을 사용해 합집합과 교집합 같은 집합 연산을 효율적으로 수행할 수 있지만, 비트 필드는 단순한 정수 열거 상수를 출력할 때보마 해석하기 훨씬 어렵다.
🍑 본론
java.util 패키지의 EnumSet 클래스는 열거 타입 상수의 값으로 구성된 집합을 효과적으로 표현해준다.
Set 인터페이스를 완벽히 구현하며, 타입 안전하고, 다른 어떤 Set 구현체와도 함께 사용할 수 있다.
EnumSet의 내부는 비트 벡터로 구현되어 있기 때문에 원소가 총 64개 이하라면 EnumSet 전체를 long 변수 하나로 표현하여 비트 필드에 비견되는 성능을 보여준다.
removeAll, retainAll과 같은 대량 작업은 비트를 효율적으로 처리할 수 있는 산술 연산을 써서 구현했다. 그러면서도 비트를 직접 다룰 때 흔히 겪는 오류들에서 해방된다.
import java.util.*;
// 코드 36-2 EnumSet - 비트 필드를 대체하는 현대적 기법
public class Text {
public enum Style {BOLD, ITALIC, UNDERLINE, STRIKETHROUGH}
public void applyStyles(Set<Style> styles) {
System.out.printf("Applying styles %s to text%n",
styles);
}
// 사용 예
public static void main(String[] args) {
Text text = new Text();
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));
}
}
applyStyles 메서드가 EnumSet<Style>이 아닌 Set<Style>을 받은 이유는?
-> 모든 클라이언트가 EnumSet을 건네리라 짐작되는 상황이라도 이왕이면 인터페이스로 받는게 일반적으로 좋은 습관이다(아이템64)
🍑 결론
열거할 수 있는 타입을 한데 모아 집합 형태로 사용한다고 해도 비트 필드를 사용할 이유는 없다. EnumSet 클래스가 비트 필드 수준의 명료함과 성능을 제공하고, 열거 타입의 장점까지 선사하기 때문이다. 유일한 단점이라면 불변 EnumSet을 만들 수 없다는 것이다.
필요하다면 Collections.unmodifiableSet으로 EnumSet을 감싸서 사용할 수 있다.
enum Weekday {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
public static void main(String[] args) {
// EnumSet 생성
EnumSet<Weekday> weekdays = EnumSet.of(Weekday.MONDAY, Weekday.TUESDAY, Weekday.WEDNESDAY);
// 불변 EnumSet 생성
Set<Weekday> immutableWeekdays = Collections.unmodifiableSet(weekdays);
// 불변 EnumSet에 요소 추가 또는 제거 시도
immutableWeekdays.add(Weekday.THURSDAY); // UnsupportedOperationException 발생
immutableWeekdays.remove(Weekday.MONDAY); // UnsupportedOperationException 발생
// 불변 EnumSet 출력
System.out.println("Immutable Weekdays: " + immutableWeekdays);
}
Collections.unmodifiableSet() 메서드는 mutableSet을 수정할 수 없는 불변 Set으로 변환하는 메서드
Chapter : 6. 열거 타입과 애너테이션
Item : 36. 비트 필드 대신 EnumSet을 사용하라
Assignee : hyunsoo10
🍑 서론
열거한 값들이 주로 집합으로 사용될 경우, 예전에는 각 상수에 서로 다른 2의 거듭제곱 값을 할당한 정수 열거 패턴(아이템 34)을 사용해 왔다.
다음과 같은 식으로 비트별 OR를 사용해 여러 상수를 하나의 집합으로 모을 수 있는데, 이렇게 만들어진 집합을 비트 필드라한다.
비트 필드를 사용하면 비트별 연산을 사용해 합집합과 교집합 같은 집합 연산을 효율적으로 수행할 수 있지만, 비트 필드는 단순한 정수 열거 상수를 출력할 때보마 해석하기 훨씬 어렵다.
🍑 본론
java.util 패키지의 EnumSet 클래스는 열거 타입 상수의 값으로 구성된 집합을 효과적으로 표현해준다. Set 인터페이스를 완벽히 구현하며, 타입 안전하고, 다른 어떤 Set 구현체와도 함께 사용할 수 있다. EnumSet의 내부는 비트 벡터로 구현되어 있기 때문에 원소가 총 64개 이하라면 EnumSet 전체를 long 변수 하나로 표현하여 비트 필드에 비견되는 성능을 보여준다.
removeAll, retainAll과 같은 대량 작업은 비트를 효율적으로 처리할 수 있는 산술 연산을 써서 구현했다. 그러면서도 비트를 직접 다룰 때 흔히 겪는 오류들에서 해방된다.
applyStyles 메서드가
EnumSet<Style>
이 아닌Set<Style>
을 받은 이유는? -> 모든 클라이언트가 EnumSet을 건네리라 짐작되는 상황이라도 이왕이면 인터페이스로 받는게 일반적으로 좋은 습관이다(아이템64)🍑 결론
열거할 수 있는 타입을 한데 모아 집합 형태로 사용한다고 해도 비트 필드를 사용할 이유는 없다. EnumSet 클래스가 비트 필드 수준의 명료함과 성능을 제공하고, 열거 타입의 장점까지 선사하기 때문이다. 유일한 단점이라면 불변 EnumSet을 만들 수 없다는 것이다.
필요하다면 Collections.unmodifiableSet으로 EnumSet을 감싸서 사용할 수 있다.
Collections.unmodifiableSet() 메서드는 mutableSet을 수정할 수 없는 불변 Set으로 변환하는 메서드
Referenced by
-