티스토리 뷰

728x90
반응형

비트 필드 대신 EnumSet을 사용하라


  • 비트 필드란 비트별 OR을 사용해 여러 상수를 하나로 모은 집합을 말합니다.

💡비트 필드 클래스 예제

  • 아래와 같은 비트 필드 열거 상수가 있다는 가정하에 text.applyStyles(STYLE_BOLD | STYPE_ITALIC); 이처럼 만들어진 집합을 비트 필드라고 합니다.
  • 이러한 비트 필드를 사용하면 비트 연산을 사용해 합집합과 교집합 같은 집합 연산을 효율적으로 수행할 수 있습니다.
  • 문제점
    • 정수 열거 상수의 단점을 그대로 가지고 있습니다.
    • 비트 필드 값이 그대로 출력되면 해석하기 어렵습니다.
    • 비트 필드 하나에 녹아 있는 모든 원소를 순회하기도 까다롭습니다.
    • 최대 몇 비트가 필요한지 API작성 시 미리 예측해 적절한 타입을 선택해야합니다.(ex: int or long)
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

    public void applyStyles(int styles) {
        ...
    }
}

 

💡대안책

  • java.util 패키지의 EnumSet 클래스는 열거 타입 상수의 값으로 구성된 집합을 효과저으로 표현해줍니다. 내부가 비트 벡터로 구현되어 있으며, 원소가 64개 이하인 경우 EnumSet 전체를 대부분 long 변수 하나로 표현하여 비트 필드에 비견되는 성능을 보여줍니다.
  • removeAll, retainAll과 같은 대량 작업은 비트를 효율적으로 처리할 수 있는 산술 연산을 써서 구현했다고 합니다.
  • 즉 비트를 직접 다를 때 겪는 문제들을 EnumSet에서 대부분 해결할 수 있습니다.
  • 아래는 EnumSet을 사용한 예제이며, 간결해지고 applyStyles 메서드를 호출할 때는 인수로 EnumSet을 전달하면 됩니다.
public class Text {

    public enum Style { 
        BOLD, ITALIC, UNDERLINE, STRIKETHROUGH 
    }
    
    //어떤 Set을 넣어도 되지만 EnumSet이 제일 좋습니다. 
    public void applyStyles(Set<Style> styleSet) {
        
        ...
    }
}

 

 

💡 applyStyles 메서드가 EnumSet<Style>이 아닌 Set<Style>을 받는 이유는 뭘까?

  • 모든 클라이언트가 EnumSet을 넘겨준다 하더라도 이왕이면 인터페이스로 받는게 일반적으로 좋은 습관입니다. 이렇게 하면 특이한 클라이언트가 다른 Set 구현체를 넘기더라도 유연하게 처리할 수 있습니다.
text.applyStyles(EnumSet.of(Style.BOLD, Style.ITALIC));

 

 

 

 

728x90
반응형