HihoBookStudy / EffectiveJava

이펙티브 자바 북스터디입니다.
1 stars 0 forks source link

[Item 36] EnumSet의 내부 구현 #36

Closed zpqmdh closed 1 month ago

zpqmdh commented 1 month ago

책 224페이지에는

EnumSet 의 내부는 비트 벡터로 구현되었다.

라고 언급하고 있습니다.

비트 벡터라는 개념이 생소해서 그런데, 비트 벡터의 간단한 개념과 비트 필드와의 차이점을 설명해주실 수 있나요? 추가로 EnumSet 의 내부가 어떻게 구현되어 있는지도 궁금합니다 !

ForteEscape commented 1 month ago

Q.

비트 벡터라는 개념이 생소해서 그런데, 비트 벡터의 간단한 개념과 비트 필드와의 차이점을 설명해주실 수 있나요? 추가로 EnumSet 의 내부가 어떻게 구현되어 있는지도 궁금합니다 !

A.

public class Client { public static void main(String[] args) { Text text = new Text();

    text.apply(Text.STYLE_BOLD | Text.STYLE_ITALIC);
}

}


- 책에서는 이 방식을 비트 필드라고 하고 있으므로 전체적으로 보았을 때 비트 벡터와 비트 필드는 동의어라고 간주할 수 있습니다.
- `EnumSet`은 두 가지의 구현체로 나뉘는데 하나는 `RegularEnumSet`과 다른 하나는 `JumboEnumSet`이 있습니다.
    - `EnumSet`은 자신이 가지는 원소의 수를 사용하여 어떤 구현체를 사용할지 결정합니다. 만약 원소가 64개 이하라면  `RegularEnumSet`을 사용하고 64개를 초과하면 `JumboEnumSet`을 사용합니다.
    - 64개가 기준인 이유는 내부 구현으로 Bit Field를 사용하기 때문인데 하나의 정수 타입으로 나타낼 수 있는 최대 원소의 개수가 64개이기 때문입니다.(1비트에 하나의 원소를 나타낸다고 한다면 `long`은 64비트이기 때문에 64개가 되겠죠?)
- `RegularEnumSet`은 64개 이하의 원소에 대해 집합을 표현합니다. 따라서 `long` 타입 변수 하나를 사용하여 데이터를 저장하게 되며 이때 `ordinal`이 사용될 수 있습니다. 코드로 표현하면 대략적으로 다음과 같습니다.
```java
    public boolean add(E e) {
        typeCheck(e);

        long oldElements = elements;
        elements |= (1L << ((Enum<?>)e).ordinal());
        return elements != oldElements;
    }