비트(Shift)가 뭔지부터 알고 가보자!

 

비트 연산자는 데이터를 비트 단위로 연산하는 것을 의미한다

 

비트 연산자 설명
& 대응되는 비트가 모두 1이면 1을 반환함. (비트 AND 연산)
| 대응되는 비트 중에서 하나라도 1이면 1을 반환함. (비트 OR 연산)
^ 대응되는 비트가 서로 다르면 1을 반환함. (비트 XOR 연산)
~ 비트를 1이면 0으로, 0이면 1로 반전시킴. (비트 NOT 연산, 1의 보수)
<< 명시된 수만큼 비트들을 전부 왼쪽으로 이동시킴. (left shift 연산)
>> 부호를 유지하면서 지정한 수만큼 비트를 전부 오른쪽으로 이동시킴. (right shift 연산)
>>> 지정한 수만큼 비트를 전부 오른쪽으로 이동시키며, 새로운 비트는 전부 0이 됨.
public class Text {
    public static final int STYLE_BOLD = 1 << 0; // 1
    public static final int STYLE_ITALIC = 1 << 1; // 2 , 01이 10이 됨
    public static final int STYLE_UNDERLINE = 1 << 2; // 4, 10이 100이 됨
    public static final int STYLE_STRIKETHROUGH = 1 << 3; // 8,  100이 1000이 됨

  // 매개변수 styles는 0개 이상의 STYLE_ 상수를 비트별 OR한 값이다.
    public void applyStyle(int style) {...}

}

다음과 같은 식으로 비트별 OR를 사용해 여러 상수를 하나의 집합으로 모을수 있으며 이렇게 만들어진 집합을 비트 필드라 한다.

 

비트 필드를 사용하면 비트별 연산을 사용해 합집합과 교집합 같은 집합 연산을 효율적으로 수행할 수 있다.

 

그러나 정수 열거 상수의 단점을 그대로 가지고 있으며 비트 필드 값이 그대로 출력되면 해석하기 힘든 단점 또한 있다.

 

그렇기 때문에 EnumSet 클래스를 이용해 열거 타입 상수의 갑스로 구성된 집합을 표현하는 것이 추천된다.

 

Set 인터페이스를 완벽히 구현하며 타입 안전하고 다른 어떤 Set구현체와도 함께 사용 가능하다.

 

추가적인 특징으로는

  • EnumSet의 내부는 비트 벡터로 구현되었다.
  • 원소가 총 64개 이하라면, 즉 대부분의 경우에 EnumSet 전체를 long 변수 하나로 표현하여 비트 필드에 비견되는 성늘 보여준다.

앞의 코드를 EnumSet으로 바꿔보았다.

public class Text {

    public enum Style { BOLD, ITALIC, UNDERLINE, STRIKETHROUGH }

    //어떤 Set을 넘겨도 되나, EnumSet이 가장 좋다.
    public void applyStyles(Set<Style> styles) {...}
}

이렇게 하면 좀 특이한 클라이언트가 다른 Set 구현체를 넘기더라도 처리할 수 있다.

+ Recent posts