๐ JAVA 04 - Collection Framework์ HashMap ๋ด๋ถ ๊ตฌ์กฐ
Java Collection Framework์ HashMap ๋ด๋ถ ๊ตฌ์กฐ
ํ์ต ๋ชฉํ
์ด๋ฒ ์ฃผ์ ์ ํต์ฌ์ ๋จ์ํ:
โHashMap์ Key-Value ์ ์ฅ ์๋ฃ๊ตฌ์กฐโ
์์ค์ด ์๋๋ค.
์ค๋ฌด์์๋ ๋ค์์ ์ดํดํด์ผ ํ๋ค.
HashMap์ ์ ๋น ๋ฅธ๊ฐ?
collision์ ์ ๋ฐ์ํ๋๊ฐ?
resize๋ ์ ์ํํ๊ฐ?
load factor๋ ์ ์กด์ฌํ๋๊ฐ?
ConcurrentHashMap์ ์ ํ์ํ๊ฐ?
CAS๋ ์ ๋ฑ์ฅํ๋๊ฐ?
๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ์ด๋ค ์ฅ์ ๊ฐ ๋ฐ์ํ๋๊ฐ?
์ฆ:
Java Collection ๋ด๋ถ ๋์๊ณผ ๋์์ฑ ์ค๊ณ ์ฒ ํ
์ ์ดํดํ๋ ๊ฒ์ด ๋ชฉํ๋ค.
Java Collection Framework ๊ตฌ์กฐ
flowchart TD
A[Collection]
A --> B[List]
A --> C[Set]
A --> D[Queue]
E[Map]
B --> F[ArrayList]
B --> G[LinkedList]
C --> H[HashSet]
E --> I[HashMap]
E --> J[ConcurrentHashMap]
HashMap ํต์ฌ ๊ตฌ์กฐ
HashMap์ ๋ด๋ถ์ ์ผ๋ก:
๋ฐฐ์ด + LinkedList + Tree
๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ค.
๊ธฐ๋ณธ ๊ตฌ์กฐ
flowchart TD
A[Bucket Array]
A --> B[Bucket 0]
A --> C[Bucket 1]
A --> D[Bucket 2]
D --> E[Node]
E --> F[Node]
F --> G[Node]
์ ๋น ๋ฅธ๊ฐ?
HashMap ํต์ฌ์:
hash ๊ฐ์ ์ด์ฉํด index ์ง์ ์ ๊ทผ
ํ๋ ๊ฒ์ด๋ค.
์:
1
index = hash(key) % bucketSize
์ฆ:
๋ฐฐ์ด ํ์์ฒ๋ผ ๋์ํ๋ค.
ํ๊ท ์๊ฐ ๋ณต์ก๋:
1
O(1)
collision์ด๋?
์๋ก ๋ค๋ฅธ key๊ฐ:
๊ฐ์ bucket index
๋ก ๋ค์ด๊ฐ๋ ํ์.
์:
1
2
"A" -> bucket 3
"B" -> bucket 3
์ collision์ด ๋ฐ์ํ๋๊ฐ?
Hash ๊ณต๊ฐ์ ์ ํ์ ์ด๋ค.
ํ์ง๋ง key๋ ๋ฌดํํ ๋ค์ด์ฌ ์ ์๋ค.
์ฆ:
์๋ฒฝํ hash๋ ํ์ค์ ์ผ๋ก ๋ถ๊ฐ๋ฅ
ํ๋ค.
collision ์ฒ๋ฆฌ ๋ฐฉ์
JDK 7:
- LinkedList ์ฌ์ฉ
JDK 8 ์ดํ:
- ์ผ์ ๊ธธ์ด ์ด์์ด๋ฉด Tree ๋ณํ
JDK8 Tree ๊ตฌ์กฐ ๋์
flowchart TD
A[Bucket]
--> B[Red-Black Tree]
์ Tree๋ฅผ ๋์ ํ๋๊ฐ?
LinkedList collision ์ฌํด์ง๋ฉด:
1
O(n)
๊น์ง ์ฑ๋ฅ ์ ํ ๋ฐ์.
ํนํ ์ ์์ hash collision ๊ณต๊ฒฉ ๊ฐ๋ฅ.
Tree ์ฌ์ฉ ์:
1
O(log n)
๋ณด์ฅ ๊ฐ๋ฅ.
resize๋?
Bucket ํฌ๊ธฐ ์ฆ๊ฐ ์์ .
์:
1
16 โ 32 โ 64
์ resize๊ฐ ํ์ํ๊ฐ?
Bucket์ด ๋ถ์กฑํ๋ฉด collision ์ฆ๊ฐ.
์ฆ:
์ฑ๋ฅ ๊ธ๊ฒฉํ ์ ํ.
load factor๋?
๊ธฐ๋ณธ๊ฐ:
1
0.75
์๋ฏธ:
1
(size / bucket capacity)
์ 0.75์ธ๊ฐ?
Trade-off ๋๋ฌธ์ด๋ค.
load factor ๋ฎ์ผ๋ฉด
์ฅ์ :
- collision ๊ฐ์
๋จ์ :
- ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น
load factor ๋์ผ๋ฉด
์ฅ์ :
- ๋ฉ๋ชจ๋ฆฌ ํจ์จ
๋จ์ :
- collision ์ฆ๊ฐ
resize๋ ์ ์ํํ๊ฐ?
resize๋:
๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฐฐ์น(rehash)
ํ๋ค.
flowchart TD
A[Old Bucket]
--> B[Rehash]
--> C[New Bucket]
์ฆ:
๋น์ฉ์ด ๋งค์ฐ ํฌ๋ค.
์ค๋ฌด์์ ์ค์ํ ์ด์
๋๋ ๋ฐ์ดํฐ insert ์:
CPU spike
latency ์ฆ๊ฐ
STW ์ฆ๊ฐ ๊ฐ๋ฅ
์ฆ:
๋์ฉ๋ ์๋น์ค์์ resize๋ ์ค์ ์ฑ๋ฅ ์ด์๋ค.
HashMap์ Thread Safeํ๊ฐ?
์๋๋ค.
๋งค์ฐ ์ค์ํ๋ค.
์ ์ํํ๊ฐ?
๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์:
๋์ put
resize ์ถฉ๋
๋ฐ์ดํฐ ์ ์ค
๋ฐ์ ๊ฐ๋ฅ.
๊ณผ๊ฑฐ JDK7 resize ๋ฌธ์
๋ฉํฐ์ค๋ ๋ resize ์:
1
2
๋ฌดํ ๋ฃจํ
CPU 100%
๋ฌธ์ ๊ฐ ์ค์ ์์๋ค.
์ ๋ช ํ ๋ฉด์ ์ง๋ฌธ์ด๋ค.
์ ๋ฐ์ํ๋๊ฐ?
resize ์ค LinkedList ๋ฐฉํฅ ๊ผฌ์ ๋ฐ์.
์ฆ:
concurrent modification ๋ฌธ์
์๋ค.
synchronized Map ๋ฌธ์
1
Collections.synchronizedMap(map)
๊ฐ๋ฅ์ ํ๋ค.
ํ์ง๋ง:
์ ์ฒด lock
์ด๋ค.
๋ฌธ์ ์
flowchart TD
A[Thread 1]
B[Thread 2]
C[Thread 3]
A --> D[Global Lock]
B --> D
C --> D
์ฆ:
๋์์ฑ ์ฑ๋ฅ์ด ๋งค์ฐ ๋จ์ด์ง๋ค.
ConcurrentHashMap ๋ฑ์ฅ
๋ชฉํ:
Thread Safe + ๋์ ๋์์ฑ
JDK7 ConcurrentHashMap
Segment ๊ธฐ๋ฐ.
flowchart TD
A[ConcurrentHashMap]
A --> B[Segment 1]
A --> C[Segment 2]
A --> D[Segment 3]
Segment๋ณ lock ์ฌ์ฉ.
JDK8 ConcurrentHashMap
๋ ๋ฐ์ ํ๋ค.
ํต์ฌ:
CAS
synchronized ์ต์ํ
bucket ๋จ์ locking
CAS๋?
Compare And Swap.
flowchart TD
A[ํ์ฌ ๊ฐ ํ์ธ]
--> B{์์๊ฐ ์ผ์น?}
B -->|YES| C[๊ฐ ๋ณ๊ฒฝ]
B -->|NO| D[์ฌ์๋]
์ ์ค์ํ๊ฐ?
๊ธฐ์กด lock ๋ฐฉ์:
1
Thread Blocking
๋ฐ์.
CAS๋:
lock ์์ด ์์์ ์ฐ์ฐ ์ํ
๊ฐ๋ฅ.
Atomic ํด๋์ค๋ CAS ์ฌ์ฉ
์:
1
2
AtomicInteger
AtomicLong
CAS ๋ฌธ์ ์
์๋ฒฝํ์ง ์๋ค.
1. Spin ๋ฌธ์
์คํจ ์ ๊ณ์ ์ฌ์๋.
CPU ์ฌ์ฉ๋ ์ฆ๊ฐ ๊ฐ๋ฅ.
2. ABA ๋ฌธ์
๊ฐ์ด:
1
A โ B โ A
๋ณ๊ฒฝ๋ผ๋ ๊ฐ์ง ๋ชปํ ์ ์์.
ConcurrentHashMap ํต์ฌ ์ฒ ํ
โlock์ ์ต๋ํ ์ค์ธ๋คโ
์ด๋ค.
์ค๋ฌด์์๋ ์ด๊ฒ ๋งค์ฐ ์ค์ํ๋ค.
์ค๋ฌด ์ฌ์ฉ ์ฌ๋ก
๋ํ์ ์ผ๋ก:
Cache
Session ์ ์ฅ
๋์ ์์ฒญ ์ํ ๊ด๋ฆฌ
API Rate Limiting
๋ฑ์ ๋ง์ด ์ฌ์ฉ.
์ฑ๋ฅ ๊ด์
HashMap:
- ๋จ์ผ Thread ์ต๊ณ ์ฑ๋ฅ
ConcurrentHashMap:
- ๋ฉํฐ Thread ์ต์ ํ
์ฆ:
์ํฉ์ ๋ฐ๋ผ ๋ค๋ฅด๋ค.
Trade-off
HashMap
์ฅ์ :
๋น ๋ฆ
๋จ์
๋จ์ :
- Thread Unsafe
synchronizedMap
์ฅ์ :
- ๊ตฌํ ์ฌ์
๋จ์ :
- ์ ์ฒด lock
ConcurrentHashMap
์ฅ์ :
๋์ ๋์์ฑ
lock ์ต์ํ
๋จ์ :
๋ด๋ถ ๊ตฌ์กฐ ๋ณต์ก
๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ์ฆ๊ฐ ๊ฐ๋ฅ
์์ฃผ ๋ฐ์ํ๋ ์ค์
1. HashMap์ ๋ฉํฐ์ค๋ ๋์์ ์ฌ์ฉ
์ค๋ฌด ์ฅ์ ๋งค์ฐ ํํจ.
2. resize ๋น์ฉ ๋ฌด์
๋๋ insert ์ ์ํ.
3. ConcurrentHashMap์ด๋ฉด ๋ฌด์กฐ๊ฑด ์์ ํ๋ค๊ณ ์ฐฉ๊ฐ
๋ณตํฉ ์ฐ์ฐ์ ์ฌ์ ํ ์ํ.
์:
1
2
3
if(map.get(key) == null) {
map.put(key, value);
}
race condition ๊ฐ๋ฅ.
๋ฉด์ ๊ผฌ๋ฆฌ ์ง๋ฌธ
Q1. HashMap์ ์ ๋น ๋ฅธ๊ฐ?
ํต์ฌ:
hash ๊ธฐ๋ฐ index ์ ๊ทผ
ํ๊ท O(1)
Q2. collision์ ์ ๋ฐ์ํ๋๊ฐ?
ํต์ฌ:
์ ํ๋ bucket ๊ณต๊ฐ
hash ์ถฉ๋ ๋ถ๊ฐํผ
Q3. JDK8์์ Tree ๊ตฌ์กฐ๋ฅผ ๋์ ํ ์ด์ ๋?
ํต์ฌ:
collision ์ฑ๋ฅ ๊ฐ์
O(log n) ๋ณด์ฅ
Q4. ConcurrentHashMap์ ์ด๋ป๊ฒ ๋์์ฑ์ ๊ฐ์ ํ๋๊ฐ?
ํต์ฌ:
CAS
lock ์ต์ํ
bucket ๋จ์ ๋๊ธฐํ
Q5. CAS๋ ๋ฌด์์ธ๊ฐ?
ํต์ฌ:
- lock-free atomic ์ฐ์ฐ
์ข์ ๋ต๋ณ ์์
HashMap์ hash ๊ธฐ๋ฐ bucket index ์ ๊ทผ์ ํตํด ํ๊ท O(1)์ ์ฑ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
ํ์ง๋ง collision ๋ฌธ์ ์ resize ๋น์ฉ์ด ์กด์ฌํ๋ฉฐ ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์๋ Thread Safeํ์ง ์์ต๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ConcurrentHashMap์ด ๋ฑ์ฅํ์ผ๋ฉฐ JDK8 ์ดํ์๋ CAS์ fine-grained locking์ ์ด์ฉํด ๋์ ๋์์ฑ์ ์ ๊ณตํฉ๋๋ค.
๋ค๋ง CAS ์ญ์ spin๊ณผ ABA ๊ฐ์ Trade-off๋ฅผ ๊ฐ์ง๋๋ค.
๊ด๋ จ CS ๊ฐ๋ ์ฐ๊ฒฐ
Hash Table
Collision Resolution
Red-Black Tree
Compare-And-Swap
Lock-Free Algorithm
Race Condition
Concurrent Programming
ํ์ ์์ ํนํ ์ค์ํ ํฌ์ธํธ
1. HashMap์ ์ ๋ Thread Safeํ์ง ์๋ค
์ค๋ฌด ์ฅ์ ๋งค์ฐ ํํ๋ค.
2. resize๋ ๋น์ฉ์ด ํฌ๋ค
๋๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ ์ค์.
3. CAS ์ดํด๋ ๋งค์ฐ ์ค์ํ๋ค
Concurrent ํ๋ก๊ทธ๋๋ฐ ํต์ฌ.
4. ConcurrentHashMap๋ ์๋ฒฝํ์ง ์๋ค
๋ณตํฉ ์ฐ์ฐ์ ์ฌ์ ํ ์ฃผ์ ํ์.
ํต์ฌ ์์ฝ
HashMap์ hash ๊ธฐ๋ฐ ์๋ฃ๊ตฌ์กฐ๋ค
collision์ ํ์ฐ์ ์ผ๋ก ๋ฐ์ํ๋ค
JDK8๋ถํฐ Tree ๊ตฌ์กฐ๋ก ์ฑ๋ฅ ๊ฐ์
resize๋ ๋งค์ฐ ๋น์ผ ์์ ์ด๋ค
HashMap์ Thread Safeํ์ง ์๋ค
ConcurrentHashMap์ CAS ๊ธฐ๋ฐ์ผ๋ก ๋์์ฑ์ ๊ฐ์ ํ๋ค
CAS๋ spin/ABA ๊ฐ์ Trade-off๋ฅผ ๊ฐ์ง๋ค
์ค๋ฌด์์๋ ๋์์ฑ ๋ฌธ์ ์ดํด๊ฐ ๋งค์ฐ ์ค์ํ๋ค