week 5 hyowon - GANGNAM-JAVA/JAVA-STUDY GitHub Wiki
ํด์์ถฉ๋์ด๋ ํด์ํจ์๊ฐ ์๋ก ๋ค๋ฅธ ๋ ๊ฐ์ ์ ๋ ฅ๊ฐ์ ๋ํด ๋์ผํ ์ถ๋ ฅ๊ฐ์ ๋ด๋ ์ํฉ์ ์๋ฏธํ๋ค.
ํด์ํจ์๋ฅผ ์ด์ฉํ ์๋ฃ๊ตฌ์กฐ๋ ์๊ณ ๋ฆฌ์ฆ์ ํจ์จ์ฑ์ ๋จ์ด๋จ๋ฆฌ๊ณ , ์ํธํ์ ํด์ํจ์์ ๊ฒฝ์ฐ ํด์ํจ์์ ์์ ์ฑ์ ๊นจ๋จ๋ฆฌ๋ ์ถฉ๋๊ณต๊ฒฉ์ด ๊ฐ๋ฅํ ์ ์๊ธฐ ๋๋ฌธ์ ์๋์ ์ธ ํด์์ถฉ๋์ ๋ง๋๋ ๊ฒ์ด ์ด๋ ต๋๋ก ์ค๊ณ๋์ด์ผ ํ๋ค.
๋น๋๊ธฐ์ง ์๋ฆฌ์ ์ํด ํด์ฌ๋งต์ ํญ์ ์ถฉ๋์ด ์๊ฒฌ๋์ด ์๋ค.
n+1๊ฐ์ ๋ฌผ๊ฑด์ n๊ฐ์ ์์์ ๋ฃ์ ๋ ์ ์ด๋ ์ด๋ ํ ์์์๋ ๋ ๊ฐ ์ด์์ ๋ฌผ๊ฑด์ด ๋ค์ด์๋ค๋ ์๋ฆฌ
ํด์๋งต์์ ํค๊ฐ์ n์๋ฆฌ์์ธ๋ฐ, ์ ๋ ฅํ ์ ์๋ ํค์ ๊ฐฏ์๋ ๋ฌดํํ๋, ๋น๋๊ธฐ์ง ์๋ฆฌ๋ฅผ ์ถฉ์กฑํ๋ค๊ณ ๋งํ ์ ์๋ค.
ํด์ ์ถฉ๋ ํด๊ฒฐ๋ฒ์ ํฌ๊ฒ ๋ ๊ฐ์ง๋ก ๋๋๋ค.
์ถฉ๋์ด ์ผ์ด๋๋ฉด ๋ค๋ฅธ ์ธ๋ฑ์ค์ ์ ์ฅํ๋๋ก ์กฐ์ ํ๋ค. ํด์ ๊ฐ๊ณผ ์ค์ ์ ์ฅ๋ ์์น๊ฐ ๋ค๋ฅผ ์ ์๋ค.
์ด๋ฏธ ์ฐจ์งํ๊ณ ์๋ ์นธ์ ๋ค์ ์นธ์ ๊ฐ์ ์ ์ฅํ๋ค.(+1, +2, ...)
๋ฐ์ดํฐ๋ค์ด ํน์ ์์น์๋ง ๋ฐ์งํ๋ ํ์(primary clustering)์ด ๋ฐ์ํ ์ ์๊ณ ๊ทธ๋ ๊ฒ ๋๋ฉด ํ์ํ๋๋ฐ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ด ์์ฒญ๋๊ฒ ๋ง์ด ์์๋๋ค.
์ด๋ฏธ ์ฐจ์งํ๊ณ ์๋ ์นธ์ n^2(n์ ์ถฉ๋ํ์)์ ๋ํ ์นธ์ ์ ์ฅํ๋ค(+1^2, +2^2, +3^2, ...).
ํ์ง๋ง ์ฒ์ ์์ ํด์๊ฐ์ด ๊ฐ์ ๊ฒฝ์ฐ, ๊ทธ ์ดํ์ ํด์๊ฐ๋ค๋ ๋ชจ๋ ๋์ผํ ๊ฐ์ผ๋ก ๊ณ์ฐ๋์ด ์ถฉ๋์ด ๋ฐ๋ณต์ ์ผ๋ก ์ผ์ด๋๋ ๋จ์ (secondary clustering)์ด ์๋ค.
ํด์ฌ ํจ์๋ฅผ ๋ ๊ฐ์ง๋ฅผ ๋๊ณ ํ์์๋ ํด์ฌํจ์1๋ง ์ฐ๋ค๊ฐ ์ถฉ๋์ ํด์ฌํจ์2๋ฅผ ์จ์ ์๋ก์ด ์ธ๋ฑ์ค๋ก ์กฐ์ ํ๋ค.
์ถฉ๋์ด ์ผ์ด๋๋ ํด๋น ์์น์ ์ ์ฅํ๋ค. ๋ค๋ง ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์จ์ ๊ธฐ์กด ๊ฐ์ ๋ฒ๋ฆฌ๊ฑฐ๋ ๋ฎ์ด์์ฐ์ง ์๊ฒ ์ ์ฅํ๋ค. ํด์ ๊ฐ๊ณผ ์ค์ ์ ์ฅ๋ ์์น๋ ๋ค๋ฅผ ์ ์๋ค.
๋ฐฐ์ด์ ์์ ์์ ๋ค์ ๋ฐฐ์ด
์ ๋ง๋ค์ด ์ ์ฅํ๋ค.
์ถฉ๋๋ ๊ฐ๋ค์ LinkedList
๋ก ์ฐ๊ฒฐํ๋ค.
Open Addressing์ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ ๋ ์ฒ๋ฆฌ๊ฐ ํจ์จ์ ์ด๊ธฐ ์ด๋ ค์ด๋ฐ, HashMap์์ remove() ๋ฉ์๋๋ ๋น๋ฒํ๊ฒ ํธ์ถ๋ ์ ์๊ธฐ ๋๋ฌธ์ Seperate Chaining์ ํ์ฉํ๋ค. ๋ํ HashMap์ ์ ์ฅ๋ key-value ๊ฐ์๊ฐ ์ผ์ ์ด์์ผ๋ก ๋ง์์ง๋ฉด, ์ผ๋ฐ์ ์ผ๋ก Open Addressing์ Separate Chaining๋ณด๋ค ๋๋ฆฌ๋ค. Open Addressing์ ๊ฒฝ์ฐ ํด์ ๋ฒํท์ ์ฑ์ด ๋ฐ๋๊ฐ ๋์์ง์๋ก Worst Case ๋ฐ์ ๋น๋๊ฐ ๋ ๋์์ง๋ค.
ํด์ ์ถฉ๋์ด ์ผ์ด๋ ๋ LinkedList
๋ง ์ฌ์ฉํ๋ค.
ํ ๋ฒํท(, ์ฆ ๊ฐ์ ํด์๊ฐ)์ key-value์์ด 8๊ฐ ์ด์์ด๋ฉด Tree
๋ก ๋ณ๊ฒฝ๋๊ณ , 6์ดํ๋ฉด LinkedList
๋ก ๋ณ๊ฒฝ๋๋ค.
8๊ณผ 6์ผ๋ก 2 ์ด์์ ์ฐจ์ด๋ฅผ ๋ ๊ฒ์, ๋ง์ฝ ์ฐจ์ด๊ฐ 1์ด๋ผ๋ฉด ์ด๋ค ํ key-value ์์ด ๋ฐ๋ณต๋์ด ์ฝ์ /์ญ์ ๋๋ ๊ฒฝ์ฐ ๋ถํ์ํ๊ฒ ํธ๋ฆฌ์ ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ ๋ณ๊ฒฝํ๋ ์ผ์ด ๋ฐ๋ณต๋์ด ์ฑ๋ฅ ์ ํ๊ฐ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ ๊ฒฐ๊ณผ get()๋ฉ์๋ ํธ์ถ์ ๋ํ ๊ธฐ๋๊ฐ์ด Java 7 ์์๋ E(N/M) ์ด์๋ค๋ฉด, Java 8์์๋ E(log(N/M))์ด ๋์๋ค.
์ด ๋๋ฌธ์ Java 7์ Entry ํด๋์ค ๋์ Java 8์์๋ TreeNode๋ฅผ ์ฌ์ฉํ ์ ์๋ Node ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ค.
ํด์ ๋ฒํท(๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋๋ ๊ณต๊ฐ)์ ๊ฐ์๊ฐ ์ ๋ค๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ์๋ ์ ์์ง๋ง ํด์ ์ถฉ๋๋ก ์ธํด ์ฑ๋ฅ์ ์์ค์ด ๋ฐ์ํ๋ค. key-value ์ ๊ฐ์๊ฐ ์ผ์ ์ด์์ด ๋๋ฉด, ํด์ ๋ฒํท์ ๊ฐ์๋ฅผ ๋ ๋ฐฐ๋ก ๋๋ฆฐ๋ค. ๊ธฐ๋ณธ๊ฐ์ 16์ด๊ณ , ์ต๋ ๊ฐ์๋ 2^30 ์ด๋ค.
์๊ณ์ = load factor * ํ์ฌ ํด์ ๋ฒํท ๊ฐ์
load factor์ ๊ธฐ๋ณธ๊ฐ์ 0.75์ด๋ค. ์๋ฅผ ๋ค๋ฉด ๋ฒํท์ ๊ฐ์๊ฐ 16๊ฐ์ผ ๋์๋ ์๊ณ์ ์ด 12๊ฐ๊ฐ ๋๋ค.
๋ค๋ง, ๋ฒํท ๊ฐ์๊ฐ ์ฆ๊ฐํ ๋๋ง๋ค ๋ชจ๋ key-value ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด ์๋ก์ด Separate Chaining์ ๊ตฌ์ฑํ๋ ๋ฌธ์ ๊ฐ ์๋ค. ๋ฐ์ดํฐ์ ๊ฐ์๋ฅผ ์์ธก ๊ฐ๋ฅํ๋ค๋ฉด, HashMap ์์ฑ์์ ์ธ์๋ก ์ด๊ธฐ ํด์ ๋ฒํท ๊ฐ์๋ฅผ ์ง์ ํ ์ ์๋ค.
// ์ธ์๋ก ์ฌ์ฉํ๋ newCapacity๋ ์ธ์ ๋ 2a์ด๋ค.
void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
// MAXIMIM_CAPACITY๋ 230์ด๋ค.
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
Entry[] newTable = new Entry[newCapacity];
// ์ ํด์ ๋ฒํท์ ์์ฑํ ๋ค์ ๊ธฐ์กด์ ๋ชจ๋ ํค-๊ฐ ๋ฐ์ดํฐ๋ค์
// ์ ํด์ ๋ฒํท์ ์ ์ฅํ๋ค.
transfer(newTable, initHashSeedAsNeeded(newCapacity));
table = newTable;
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
// ๋ชจ๋ ํด์ ๋ฒํท์ ์ํํ๋ฉด์
for (Entry<K,V> e : table) {
// ๊ฐ ํด์ ๋ฒํท์ ์๋ ๋งํฌ๋ ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ฉด์
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
// ํด์ ๋ฒํท ๊ฐ์๊ฐ ๋ณ๊ฒฝ๋์๊ธฐ ๋๋ฌธ์
// index ๊ฐ(hashCode % M)์ ๋ค์ ๊ณ์ฐํด์ผ ํ๋ค.
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
๊ทธ๋ฐ๋ฐ ์ด๋ ๊ฒ ํด์ ๋ฒํท ํฌ๊ธฐ๋ฅผ ๋ ๋ฐฐ๋ก ํ์ฅํ๋ ๊ฒ์๋ ๊ฒฐ์ ์ ์ธ ๋ฌธ์ ๊ฐ ์๋ค. ํด์ ๋ฒํท์ ๊ฐ์ M์ด 2a ํํ๊ฐ ๋๊ธฐ ๋๋ฌธ์, index = X.hashCode() % M์ ๊ณ์ฐํ ๋ X.hashCode()์ ํ์ a๊ฐ์ ๋นํธ๋ง ์ฌ์ฉํ๊ฒ ๋๋ค๋ ๊ฒ์ด๋ค. ์ฆ ํด์ ํจ์๊ฐ 32๋นํธ ์์ญ์ ๊ณ ๋ฅด๊ฒ ์ฌ์ฉํ๋๋ก ๋ง๋ค์๋ค ํ๋๋ผ๋ ํด์ ๊ฐ์ 2์ ์น์๋ก ๋๋๋ฉด ํด์ ์ถฉ๋์ด ์ฝ๊ฒ ๋ฐ์ํ ์ ์๋ค.
์ด ๋๋ฌธ์ ๋ณด์กฐ ํด์ ํจ์๊ฐ ํ์ํ๋ค.
index = X.hashCode() % M์ ๊ณ์ฐํ ๋ ์ฌ์ฉํ๋ M ๊ฐ์ ์์์ผ ๋ index ๊ฐ ๋ถํฌ๊ฐ ๊ฐ์ฅ ๊ท ๋ฑํ ์ ์๋ค. ๊ทธ๋ฌ๋ M ๊ฐ์ด ์์๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ๋ณ๋์ ๋ณด์กฐ ํด์ ํจ์๋ฅผ ์ด์ฉํ์ฌ index ๊ฐ ๋ถํฌ๊ฐ ๊ฐ๊ธ์ ๊ท ๋ฑํ ์ ์๋๋ก ํด์ผ ํ๋ค.
๋ณด์กฐ ํด์ ํจ์(supplement hash function)์ ๋ชฉ์ ์ 'ํค'์ ํด์ ๊ฐ์ ๋ณํํ์ฌ, ํด์ ์ถฉ๋ ๊ฐ๋ฅ์ฑ์ ์ค์ด๋ ๊ฒ ์ด๋ค. ์ด ๋ณด์กฐ ํด์ ํจ์๋ JDK 1.4์ ์ฒ์ ๋ฑ์ฅํ๋ค. Java 5 ~ Java 7์ ๊ฐ์ ๋ฐฉ์์ ๋ณด์กฐ ํด์ ํจ์๋ฅผ ์ฌ์ฉํ๊ณ , Java 8๋ถํฐ๋ ๋ค์ ์๋ก์ด ๋ฐฉ์์ ๋ณด์กฐ ํด์ ํจ์๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค.
java 8
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
์ ์ฝ๋๋ Horner's method๋ฅผ ๊ตฌํํ ๋ฐฉ์์ผ๋ก, ๋จํญ์์ ์ฌ๊ท์ ์ผ๋ก ์ฌ์ฉํ์ฌ ๋คํญ์ ์ฐ์ฐ์ ํํํ์๋ค.
String ๊ฐ์ฒด ํด์ ํจ์์์ 31์ ์ฌ์ฉํ๋ ์ด์
- 31์ด ์์ ์ด๋ฉฐ ๋ํ ์ด๋ค ์์ 31์ ๊ณฑํ๋ ๊ฒ์ ๋น ๋ฅด๊ฒ ๊ณ์ฐํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
- 31N=32N-N์ธ๋ฐ, 32๋ 25์ด๋ ์ด๋ค ์์ ๋ํ 32๋ฅผ ๊ณฑํ ๊ฐ์ shift ์ฐ์ฐ์ผ๋ก ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ค. ๋ฐ๋ผ์ N์ 31์ ๊ณฑํ ๊ฐ์, (N << 5) โ N๊ณผ ๊ฐ๋ค. 31์ ๊ณฑํ๋ ์ฐ์ฐ์ ์ด๋ ๊ฒ ์ต์ ํ๋ ๋จธ์ ์ฝ๋๋ก ์์ฑํ ์ ์๊ธฐ ๋๋ฌธ์, String ํด๋์ค์์ ํด์ ๊ฐ์ ๊ณ์ฐํ ๋์๋ 31์ ์น์๋ก ์ฌ์ฉํ๋ค.
https://stdin2stdout.tistory.com/entry/Q-ํด์ฌ-์ถฉ๋์ด-๋ฌด์์ด๊ณ -ํด๊ฒฐ์ฑ ์-์๊ณ -์๋์