back-end-study / effective-java

🔥 이펙티브 자바 스터디
43 stars 4 forks source link

[Item64, 72] 객체는 인터페이스를 참조하라, 표준예외를 사용하라 #93

Closed youngreal closed 1 year ago

jun108059 commented 1 year ago

p369 2번째 문단
이를 EnumMap으로 바꾸면 속도가 빨라지고 순회 순서도 키의 순서와 같아진다.

EnumMap과 HashMap의 구조 차이가 궁금합니다. 왜 EnumMap은 속도가 더 빠를까요?! @youngreal

youngreal commented 1 year ago

HashMap과 EnumMap

HashMap은 EnumMap에 비해 고려해야할게 3가지가 있습니다

1. 해싱

image

HashMap은 Key로 들어올값이 무한하며 인덱스는 한정되어있어 해시충돌이 불가피합니다.

이 해시충돌을 최대한 줄이기위해 key값을 입력받으면 항상 해시함수를 이용해 값을 받게됩니다.

EnumMap은 Key값이 한정되어있기때문에 해시충돌을 줄이고자 해시함수를 이용하는 과정이 없습니다.

2. 해시 충돌

image

(키,값을 가진 노드로 관리하고, TREEIFY_THRESHOLD(8) 이상일경우 treeifyBin(트리로 전환) 메서드를 호출)

HashMap은 해시충돌 발생시 버킷을 LinkedList로 관리(O(N)), 자바8부터는 LinkedList의 요소가 8개가 넘으면 레드블랙트리로 관리합니다 O(LogN)

반면, EnumMap은 Key로 들어올 값들이 Enum의 상수들로 한정되어있고

해시충돌을 염두 할일이 없기때문에 항상 O(1)로 값을 꺼낼수있습니다.

3. 재해싱(resize)

HashMap은 현재 사이즈의 0.75배(버킷의 4분의3이 차면 해시 충돌발생가능성이 높다고 판단한 지표값)의 공간이 차버리면 사이즈를 2배로 늘리는 재해싱 과정도 불가피합니다.

image

(재배치 하는과정)

이때 기존에 있던 버킷의 값들 전부 다시 읽어 재배치 하기때문에 O(N)의 시간이 걸립니다.

EnumMap은 Key의 개수가 Enum의 상수객체의 수로 이미 정해지기때문에 이 과정을 염두할일이 적습니다.

정리

HashMap은 항상 Key값을 해싱해서 관리하는 과정이 포함되어있으며, 해시충돌, 재해싱 과정을 피할수없습니다.

반면, EnumMap의 Key가 될수있는값들은 한정되어있어 위의 세가지 과정에 걸리는 비용이 소모되지않습니다.

결국 Key가 될수있는 값들의 개수, 범위에 제한이 있냐 없냐 차이로 인해 생기는 비용으로 인해 EnumMap이 성능이 더 좋다고 할수있습니다.

더 궁금하신점이 있다면 말씀주세요!!