glenn-syj / more-effective-java

이펙티브 자바를 읽으며 자바를 더 효율적으로 공부합니다
4 stars 5 forks source link

[MEJ-008] 불변 EnumSet에 대한 보충 설명 #163

Closed undeadtimo closed 1 month ago

undeadtimo commented 2 months ago

Based on: https://github.com/glenn-syj/more-effective-java/commit/bacd47801a89045ba2a814bbf3822ae9a07fa9f1 @glenn-syj

EnumSet에 대해 깔끔하게 정리한 글을 공유해주셔서 감사합니다.

덕분에, 책 본문에 나와있는 것 외의 다른 EnumSet에 대한 특성을 알 수 있었습니다.

특히, 비트 벡터에 대해서 구현체별로 어떻게 비트를 표현하고 있는지 알게되었습니다.

다만, 저는 본문을 읽으면서 불변 형태의 EnumSet에 대한 생성 기능을 Java에서 직접적으로 제공하지 않고, 다른 라이브러리를 사용하거나 EnumSet과 유사한 형태를 만드는 방식만이 존재한다고 하여,

어떻게 불변 형태의 EnumSet을 생성하는지 궁금증이 생겨 그 부분에 대해 조사해보았습니다.


  1. EnumSet이 아닌 Set에 열거 타입 데이터를 넣어서 불변 형태로 만들기.
Set<MyEnum> set = Set.of(MyEnum.VALUE1, MyEnum.VALUE2);

자바9 부터는 Set의 메서드 of를 사용하여 불변 형태의 Set을 만들 수 있습니다.

그러나 이는, Enum에서 사용되는 타입과 데이터를 가져왔을 뿐, EnumSet이 아닌 Set을 다루는 것이기 때문에 EnumSet이 가지고 있는 여러 장점과 특성을 활용할 수 없게 됩니다.

  1. 구글 Guava 라이브러리의 ImmutableSet 사용하기.

사실 Guava 라이브러리의 ImmutableSet을 사용한다고 해도 완전한 불변형 EnumSet을 생성할 수 있는 것은 아닙니다.

ImmutableSet또한 EnumSet이 아닌 Set을 다루는 것일 뿐이지만, Set.of을 이용하여 생성한 것과는 다르게 EnumSet과 유사한 기능을 어느정도 가지고 있습니다.

예를 들면, ImmutableSet 또한 제네릭을 사용하여 EnumSet처럼 타입 안정성을 제공할 수 있다는 유사점이 존재합니다.

그러나, EnumSet은 열거형 타입만을 관리하지만 ImmutableSet은 어떤 타입이든 저장할 수 있다는 차이점 또한 존재합니다.

  1. Collections.unmodifiableSet 이용하기.
// EnumSet 생성
EnumSet<MyEnum> enumSet = EnumSet.of(MyEnum.VALUE1, MyEnum.VALUE2);

// unmodifiableSet 생성
Set<MyEnum> unmodifiableSet = Collections.unmodifiableSet(enumSet);

이 방법 또한 안타깝게도 완전한 불변형 EnumSet을 생성해주지는 않습니다.

대신, 읽기 전용인 '불변' Set을 따로 만들어주고 있습니다.

다시 말하면, 원본 EnumSet은 그대로 존재하고, 그것을 복사한 불변 형태의 Set을 생성하는 것입니다.

따라서 기존의 EnumSet은 수정이 가능하고, 기존 EnumSet을 수정할 경우, Collections.unmodifiableSet을 이용하여 생성한 읽기 전용 Set의 데이터 또한 갱신됩니다.


결과적으로, EnumSet에 대한 완전한 불변형은 외부 라이브러리를 사용하다고 해도 생성이 불가능합니다.

Java의 개발자가 EnumSet에 대한 불변형을 제공하지 않는 이유는 무엇인지 추가적인 의문이 들기에 계속해서 그 의문에 대해 탐구해보도록 하겠습니다.


References :

https://docs.oracle.com/javase%2F9%2Fdocs%2Fapi%2F%2F/java/util/Set.html

https://stackoverflow.com/questions/28413670/immutable-version-of-enumset

glenn-syj commented 2 months ago

제 생각에는 Collections 자체가 일단 manipulation을 위해서 만들어진 Framework의 패키지라서 그런 것 같기도 합니다. 물론 그래서 스레드 안전성이 콜렉션을 다룰 때 어려운 지점이 되기도 하지만요.

대신 Kotlin에서는 컬렉션을 확장하여 가변형 컬렉션과 불변형 컬렉션이 존재합니다. 일반적인 불변형은 setOf와 같은 메서드를 통해서, 일반적인 가변형은 mutableSetOf와 같은 메서드를 통해서 처리한다는 사실!

References

https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html https://kotlinlang.org/docs/collections-overview.html#collection

undeadtimo commented 1 month ago

공식문서에서도 정확히 'unified architecture for representing and manipulating collections' 이라고 표시하고 있군요.

추가적으로 원래 관심있던 Kotlin에 대한 정보까지 알려주시니 더 흥미가 생기네요, 감사합니다!