Programming/Java

[Effective Java] μ™œ EnumSet κ³Ό EnumMap 을 μ‚¬μš©ν•΄μ•Ό ν•˜λŠ”κ°€

osean 2022. 11. 20. 19:20

λ“€μ–΄κ°€κΈ° 전에

λ°±κΈ°μ„ λ‹˜μ˜ [Effective Java] κ°•μ˜λ₯Ό μˆ˜κ°•ν•˜λŠ” 쀑 μ—¬λŸ¬ 개의 Enum 객체λ₯Ό κ°€μ§€κ±°λ‚˜ Enum 객체λ₯Ό Key 둜 κ°€μ§€λŠ” 경우 μ™œ EnumMap μ΄λ‚˜ EnumSet 을 μ“°λŠ” 것이 λ‹€λ₯Έ Map / Set κ΅¬ν˜„μ²΄λ₯Ό μ‚¬μš©ν•˜λŠ” 것보닀 νš¨μœ¨μ μΈμ§€μ— λŒ€ν•΄ ν•™μŠ΅ν•˜λŠ” 과제λ₯Ό λ°›μ•˜λ‹€. 이번 μ‹œκ°„μ—λŠ” 이듀이 λ™μž‘ν•˜λŠ” 방식과 그에 λŒ€ν•œ 차이점 및 얻을 수 μžˆλŠ” 이점에 λŒ€ν•΄μ„œ μ‚΄νŽ΄λ³΄λ €κ³  ν•œλ‹€.


μ™œ μ—΄κ±° νƒ€μž…μ„ μ‚¬μš©ν•΄μ•Ό ν• κΉŒ?

Java 1.5 버전 μ΄μ „μ—λŠ” 자주 μ‚¬μš©ν•˜λŠ” μƒμˆ˜λ₯Ό int νƒ€μž…μœΌλ‘œ μ •μ˜ν•˜μ—¬ μ‚¬μš©ν–ˆλ‹€. 이λ₯Ό μ •μˆ˜ μ—΄κ±° νŒ¨ν„΄μ΄λΌκ³  ν•œλ‹€. 과거의 λ°©μ‹μ²˜λŸΌ int λ₯Ό μ΄μš©ν•΄ μƒμˆ˜λ₯Ό μ—΄κ±°ν•˜λŠ” 경우 λ‹€μŒκ³Ό 같은 문제λ₯Ό μ•ΌκΈ°ν•  수 μžˆλ‹€.

1. 컴파일 νƒ€μž„μ—μ„œ νƒ€μž… μ•ˆμ „μ„±μ„ 보μž₯ν•  수 μ—†λ‹€.
2. Name Space λ₯Ό κ°€μ§ˆ 수 μ—†κΈ° λ•Œλ¬Έμ— λ™μΌν•œ 이름에 λŒ€ν•΄μ„œ 접두사λ₯Ό μΆ”κ°€ν•΄ ν˜Όλž€μ„ ν”Όν•΄μ•Ό ν•˜λ©°, 가독성을 λ–¨μ–΄νŠΈλ¦°λ‹€.
3. μ˜λ―Έκ°€ μ„œλ‘œ λ‹€λ₯Έ μƒμˆ˜λΌλ„ 동등 비ꡐ μ—°μ‚° μ‹œ, ν•΄λ‹Ή μƒμˆ˜μ˜ μ •μˆ˜κ°’μ΄ 같은 경우 True λ₯Ό λ°˜ν™˜ν•˜κ³  μ»΄νŒŒμΌλŸ¬λŠ” μ•„λ¬΄λŸ° κ²½κ³  메세지λ₯Ό 좜λ ₯ν•˜μ§€ μ•Šμ•„ κ°œλ°œμžκ°€ λΆ€μ—¬ν•œ 의미, μ˜λ„μ™€λŠ” λ‹€λ₯΄κ²Œ μž‘λ™ν•  수 μžˆλ‹€.

μ΄λŸ¬ν•œ μ •μˆ˜ μ—΄κ±° νŒ¨ν„΄μ˜ 단점은 Java 1.5 λΆ€ν„° λ“±μž₯ν•œ Enum 을 μ΄μš©ν•˜λ©΄ ν•΄κ²°ν•  수 μžˆλ‹€.
C, CPP λ“±κ³Ό 같은 언어와 λΉ„μŠ·ν•˜μ§€λ§Œ μ΅œμ’…μ μœΌλ‘œλŠ” μ°Έμ‘° νƒ€μž…(ν•˜λ‚˜μ˜ 클래슀) 이기 λ•Œλ¬Έμ— 훨씬 더 κ°•λ ₯ν•˜λ‹€. Enum 에 각 역할에 λ§žλŠ” 멀버 속성을 μΆ”κ°€ν•˜κ±°λ‚˜ 역할에 λ§žλŠ” λ©”μ†Œλ“œλ₯Ό μ •μ˜ν•΄ μ—΄κ±° νƒ€μž… λ³„λ‘œ λΆ€μ—¬λœ κ·Έ μ˜λ―Έμ— λŒ€ν•œ μ±…μŒμ„ μ˜¨μ „νžˆ λ‹€ν•  수 μžˆλ‹€.

Java 의 Enum 은 μƒμˆ˜ ν•˜λ‚˜λ‹Ή μžμ‹ μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό ν•˜λ‚˜μ”© λ§Œλ“€μ–΄ public static final ν•„λ“œλ‘œ κ³΅κ°œν•˜κ³ , μ™ΈλΆ€μ—μ„œ μ ‘κ·Όν•  수 μžˆλŠ” μƒμ„±μžλ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 사싀상 final 의 의미λ₯Ό 가진닀. 즉, JVM μƒμ—μ„œ Enum 은 단 ν•˜λ‚˜λ§Œ μ‘΄μž¬ν•˜λŠ” 것이닀. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— Singleton νŒ¨ν„΄μ€ μ›μ†Œκ°€ ν•˜λ‚˜μΈ μ—΄κ±° νƒ€μž…μ΄λΌκ³  ν•  수 있으며, ν˜Ήμ€ μ—΄κ±° νƒ€μž…μ€ Singleton 을 μΌλ°˜ν™”ν•œ ν˜•νƒœλΌκ³  ν•  수 μžˆλ‹€.

λ˜ν•œ, Enum 은 μ•žμ„œ λ§ν•œ 것과 같이 ν•˜λ‚˜μ˜ 클래슀이기 λ•Œλ¬Έμ— μ»΄νŒŒμΌνƒ€μž„ νƒ€μž… μ•ˆμ „μ„±μ„ μ œκ³΅ν•œλ‹€.
λ•Œλ¬Έμ— 기쑴의 μ •μˆ˜ μ—΄κ±° νŒ¨ν„΄μ„ μ΄μš©ν•˜λ©΄ μ»΄νŒŒμΌνƒ€μž„μ—μ„œ μ²΄ν¬ν•˜μ§€ λͺ»ν•΄ λ‹€λ₯Έ 의미의 μƒμˆ˜λ”λΌλ„ κ·ΈλŒ€λ‘œ 값이 λ°˜ν™˜λ˜μ—ˆλ‹€λ©΄, Enum 의 정해진 EnumType 만 λ°˜ν™˜ν•  수 μžˆκΈ°μ— λ‹€λ₯Έ νƒ€μž…μ˜ Enum 을 λ„˜κΈ°λ €κ³  ν•˜λŠ” 경우 컴파일 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.


μ™œ EnumSet κ³Ό EnumMap 을 μ‚¬μš©ν•΄μ•Ό ν• κΉŒ?

EnumSet?

EnumSet 은 universe λΌλŠ” Enum 배열을 멀버 μ†μ„±μœΌλ‘œ 가지고, universe 의 length() λ°˜ν™˜κ°’μ„ κΈ°μ€€μœΌλ‘œ RegularEnumSet ν˜Ήμ€ JumboEnumSet 으둜 λΆ„κΈ° μ²˜λ¦¬ν•˜μ—¬ κ΅¬ν˜„μ²΄λ₯Ό λ°˜ν™˜ν•œλ‹€. μ™œ ꡳ이 universe 의 length() λ₯Ό κΈ°μ€€μœΌλ‘œ, 64 λΌλŠ” νŠΉμ •μ μΈ 값을 κΈ°μ€€μœΌλ‘œ ν•΄μ„œ κ΅¬ν˜„μ²΄λ₯Ό λ‚˜λˆ„μ–΄ λ°˜ν™˜ν•˜λŠ”κ±ΈκΉŒ?

RegularEnumSet 은 long 의 bit λ²”μœ„λ₯Ό κΈ°μ€€μœΌλ‘œ ν‘œν˜„ν•  수 μžˆλŠ” κ²½μš°μ— μ‚¬μš©λ˜κ³ , JumboEnumSet 은 long 의 bit λ²”μœ„λ₯Ό μ΄ˆκ³Όν•˜λŠ” κ²½μš°μ— μ‚¬μš©λœλ‹€. κ·Έλž˜μ„œ RegularEnumSet κ³Ό JumboEnumSet 의 elements 멀버 속성은 각각 long κ³Ό long[] 둜 λ‹€λ₯΄λ‹€.

이 λ•Œ, EnumSet 의 κ΅¬ν˜„μ²΄λ“€μ€ μ™œ long νƒ€μž…μ„ μ΄μš©ν•˜λŠ”κ±ΈκΉŒ?
μ΄λŠ” λΉ„νŠΈ 연산을 μ‚¬μš©ν•˜κΈ° μœ„ν•¨μœΌλ‘œ Enum 의 μœ„μΉ˜λ₯Ό λΉ„νŠΈλ‘œ λ‚˜νƒ€λƒ„μœΌλ‘œμ¨ ν•΄λ‹Ή λΉ„νŠΈ μœ„μΉ˜μ— Enum 의 쑴재 μ—¬λΆ€λ₯Ό ꡉμž₯히 λΉ λ₯΄κ²Œ νŒŒμ•…ν•  수 있기 λ•Œλ¬Έμ΄λ‹€. λ‹€λ§Œ universe 둜 λ“€μ–΄μ˜¨ λ°μ΄ν„°μ˜ 개수(μ €μž₯ν•  λ°μ΄ν„°μ˜ 수) κ°€ μ•„λ‹Œ ν•΄λ‹Ή Enum 에 μ •μ˜λœ μƒμˆ˜μ˜ 개수λ₯Ό λ°”νƒ•μœΌλ‘œ elements λ₯Ό κ³ λ €ν•œλ‹€.

μœ„μ™€ 같은 λ°©λ²•μœΌλ‘œ 데이터λ₯Ό μ €μž₯ν•˜κΈ° λ•Œλ¬Έμ— EnumSet 은 μ‚°μˆ  λΉ„νŠΈ 연산을 μ΄μš©ν•΄ κ΅¬ν˜„λ˜μ–΄ μžˆλ‹€.
μ‚°μˆ  λΉ„νŠΈ 연산은 일정 μ‹œκ°„ 내에 μ‹€ν–‰λ˜κΈ° λ•Œλ¬Έμ— 맀우 λΉ λ₯΄κ²Œ 연산을 μ²˜λ¦¬ν•  수 있으며, 이둜 인해 Set 의 λ‹€λ₯Έ κ΅¬ν˜„μ²΄λ“€κ³Ό 달리 더 λΉ λ₯΄κ²Œ λ°μ΄ν„°μ˜ μœ„μΉ˜λ₯Ό νŒŒμ•…ν•  수 있으며 λ³„λ„λ‘œ hashCode λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ•„λ„ λ˜λŠ” μž₯점이 μžˆλ‹€.

μ΄λŸ¬ν•œ νŠΉμ§•μœΌλ‘œ 인해 EnumSet 이 λ©”λͺ¨λ¦¬λ₯Ό μ°¨μ§€ν•˜λŠ” λΉ„μœ¨μ΄ 적어 ꡉμž₯히 μ••μΆ•μ μ΄λ©΄μ„œ 효율적이기 λ•Œλ¬Έμ— μ—¬λŸ¬ Enum 데이터λ₯Ό μ €μž₯ν•΄μ•Ό ν•˜λŠ” 경우, Set 의 κ΅¬ν˜„μ²΄λ₯Ό μ΄μš©ν•˜λŠ” 것보닀 EnumSet 을 μ΄μš©ν•˜λŠ” 것을 λ¨Όμ € κ³ λ €ν•΄μ•Ό ν•œλ‹€.

EnumMap?

κ·Έλ ‡λ‹€λ©΄ Enum 을 Key 둜 κ°€μ§€λŠ” Map 객체λ₯Ό κ³ λ €ν•  λ•Œ μ™œ EnumMap κ΅¬ν˜„μ²΄λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 더 효율적일까?
κ·Έ μ΄μœ λŠ” λ°”λ‘œ EnumMap 은 Key 와 Value κ°€ λ°°μ—΄λ‘œ μ •μ˜λ˜μ–΄ 있기 λ•Œλ¬Έμ΄λ‹€.

HashMap 클래슀λ₯Ό μ‚΄νŽ΄λ³΄λ”λΌλ„ HashMap 은 EnumMap κ³ΌλŠ” 달리 Node λΌλŠ” Inner Class λ₯Ό κ΅¬ν˜„ν•˜κ³  이λ₯Ό 멀버 μ†μ„±μœΌλ‘œ μ‚¬μš©ν•˜κ³  μžˆλ‹€. μ΄λŠ” ꢁ극적으둜 λ©”λͺ¨λ¦¬λ₯Ό μ‚¬μš©ν•˜λŠ” 데에 μžˆμ–΄μ„œ EnumMap 이 훨씬 μœ λ¦¬ν•˜λ‹€.

배열을 멀버 μ†μ„±μœΌλ‘œ μ‚¬μš©ν•˜λŠ” EnumMap 의 경우 Enum 내뢀에 μ •μ˜λœ μƒμˆ˜μ˜ 개수만큼 Key 와 Value 의 길이λ₯Ό μ •μ˜ν•˜κΈ° λ•Œλ¬Έμ— λ³„λ„λ‘œ 객체의 크기λ₯Ό 리사이징 ν•  ν•„μš”κ°€ μ—†μ§€λ§Œ(배열이 μ„ μ–Έλ˜λ©΄μ„œ λ©”λͺ¨λ¦¬μ— ν• λ‹Ήλ˜λŠ” 크기λ₯Ό μ œν•œν•œλ‹€.), HashMap 의 경우 μ΄ˆκΈ°ν™”λœ 길이λ₯Ό μ΄ˆκ³Όν•˜λŠ” 경우 객체의 크기λ₯Ό μž¬μ •μ˜ ν•˜λ©΄μ„œ λ©”λͺ¨λ¦¬ λ¦¬μ†ŒμŠ€λ₯Ό 많이 μ†Œλͺ¨ν•˜κ²Œ λœλ‹€. 

λ˜ν•œ, HashMap 은 각 λ…Έλ“œλ§ˆλ‹€ HashCode λ₯Ό λΆ€μ—¬ν•˜μ—¬ λ°μ΄ν„°μ˜ ν•΄μ‹œ μΆ©λŒμ„ λ°©μ–΄ν•΄μ•Ό ν•˜μ§€λ§Œ, EnumMap 은 Key κ°€ μ• μ΄ˆμ— λ©”λͺ¨λ¦¬ 상에 ν•˜λ‚˜λ§Œ μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ— μ΄λŸ¬ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•  ν•„μš”κ°€ μ—†λ‹€.

μ΄λŸ¬ν•œ μ„±λŠ₯ 상 이점 λ•Œλ¬Έμ— Key λ₯Ό Enum 으둜 λ°›λŠ” 경우 EnumMap κ΅¬ν˜„μ²΄λ₯Ό κΌ­ κ³ λ €ν•˜μ—¬ ν”„λ‘œκ·Έλž¨μ„ μ„€κ³„ν•˜λŠ” 것이 μ’‹λ‹€.


λ§ˆλ¬΄λ¦¬ν•˜λ©°

업무 쀑에 @Converter λ₯Ό μ΄μš©ν•΄ DB μ—μ„œ 가지고 μ˜€λŠ” 데이터λ₯Ό EnumSet / EnumMap 으둜 λ°”μΈλ”©ν•˜λŠ” μž‘μ—…μ΄ ν•„μš”ν•˜κ²Œ λ˜λ©΄μ„œ μš°μ—°νžˆ EnumSet / EnumMap 에 λŒ€ν•΄μ„œ μ•Œκ²Œ λ˜μ—ˆλŠ”λ°, λ‹Ήμ‹œμ—λŠ” μ™œ ꡳ이 μ΄λŸ¬ν•œ κ΅¬ν˜„μ²΄λ₯Ό 써야 ν•˜λŠ”μ§€ μ•Œμ§€λ„, μ•Œλ €κ³ λ„ ν•˜μ§€ μ•Šμ•˜λ‹€.

μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” μ΄μœ λ„ λͺ¨λ₯Έ 채 κ·Έλƒ₯ μ½”λ“œ 볡사 / λΆ™μ—¬λ„£κΈ°λ§Œ ν•˜λ˜ 과거의 λ‚˜λ₯Ό λ°˜μ„±ν•˜λ©°, μ–΄λ– ν•œ μ΄μœ μ™€ 의미λ₯Ό 가지고 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λŠ”μ§€ 깊이 μƒκ°ν•΄μ•Όκ² κ΅¬λ‚˜ λŠλ‚€ μ‹œκ°„μ΄μ—ˆλ‹€. μ•žμœΌλ‘œ 더 κ³ κ΅°λΆ„νˆ¬ν•  수 있기λ₯Ό!


참고자료

 

Using Bit Flags and EnumSets in Java · Edd Mann

Using Bit Flags and EnumSets in Java 20 Dec 2013 Bit Flags Bit flags, commonly referred to as Bit fields are an efficient way of storing several related boolean values in a single primitive type. Internally represented in binary, you can decide on how larg

eddmann.com

 

[JAVA] EnumMap 을 μ‚¬μš©ν•©μ‹œλ‹€.

 

www.manty.co.kr

 

λ°±κΈ°μ„ λ‹˜ 온라인 μŠ€ν„°λ”” 11μ£Όμ°¨-Enum

enum에 λŒ€ν•΄μ„œ μ•Œκ³ μžˆλŠ” 것보닀 μ’€ 더 깊이 μ•Œμ•„λ΄…μ‹œλ‹€.

velog.io

 

Enum (Java SE 11 & JDK 11 )

 

docs.oracle.com

 

'Programming > Java' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

F019 - Socket  (0) 2021.06.22
F018 - Serializable (직렬화, 역직렬화)  (0) 2021.06.16
F017 - Blocking, Non-Blocking / Synchronous, Asynchronous  (2) 2021.06.15
F016 - File, I/O, Stream  (0) 2021.06.14
F015 - Set (μž‘μ„± 쀑)  (0) 2021.05.31