๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋นˆ ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ

[Java] HashMap ๊ตฌํ˜„

์ถœ์ฒ˜

ChatGPT

์ž๋ฐ” 1.8 ์†Œ์Šค ์ฝ”๋“œ


์ž๋ฐ”์˜ HashMap์€ ์ž๋ฐ” ์ปฌ๋ ‰์…˜ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ ์ค‘ ํ•˜๋‚˜๋กœ, ํ‚ค-๊ฐ’ ์Œ(key-value pair)์„ ์ €์žฅํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. HashMap์€ ํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ, ํ‚ค๋ฅผ ํ•˜์‹œ ํ•จ์ˆ˜๋กœ ๋ณ€ํ™˜ํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ €์žฅํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ๋‹ค.

 

1. HashMap์˜ ์ฃผ์š” ํŠน์ง•

์ƒ์ˆ˜ ์‹œ๊ฐ„ ์„ฑ๋Šฅ

์ผ๋ฐ˜์ ์œผ๋กœ HashMap์—์„œ ์‚ฝ์ž…, ์‚ญ์ œ, ์กฐํšŒ๋Š” O(1) ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง„๋‹ค. ์ฆ‰, ๋งค์šฐ ๋น ๋ฅธ ์ ‘๊ทผ ์„ฑ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. ํ•˜์ง€๋งŒ ํ•ด์‹œ ์ถฉ๋Œ์ด ๋งŽ์•„์งˆ ๊ฒฝ์šฐ, ์„ฑ๋Šฅ์€ O(n)๊นŒ์ง€ ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

๋น„๋™๊ธฐ์ 

HashMap์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™๊ธฐํ™”๋˜์ง€ ์•Š์œผ๋ฉฐ, ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๋™์‹œ์— ์ˆ˜์ •๋  ๊ฒฝ์šฐ ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค. ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ, Collections.sysnchronizedMap()์œผ๋กœ ๋™๊ธฐํ™”๋œ ๋งต์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

null ํ—ˆ์šฉ

HashMap์€ null ํ‚ค์™€ null ๊ฐ’์„ ํ—ˆ์šฉํ•œ๋‹ค. ๋‹จ, null ํ‚ค๋Š” ํ•˜๋‚˜๋งŒ ์ €์žฅํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, null ๊ฐ’์€ ์—ฌ๋Ÿฌ ๊ฐœ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

 

2. HashMap์˜ ๋‚ด๋ถ€ ๊ตฌ์กฐ

HashMap์€ ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฐฐ์—ด๊ณผ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ(๋˜๋Š” ํŠธ๋ฆฌ ๊ตฌ์กฐ)๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค. ์ด ๋ฐฐ์—ด์€ ๋ฒ„ํ‚ท(bucket)์ด๋ผ๊ณ  ํ•˜๋ฉฐ, ๊ฐ ๋ฒ„ํ‚ท์—๋Š” ํ•ด์‹œ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ ๋˜๋Š” ํŠธ๋ฆฌ๊ฐ€ ์ €์žฅ๋œ๋‹ค.

1. ํ•ด์‹œ ๋ฒ„ํ‚ท ๊ตฌ์กฐ

  • HashMap์€ ํ•ด์‹œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ํ‚ค๋ฅผ ํŠน์ • ์ธ๋ฑ์Šค๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ํ•ด๋‹น ์ธ๋ฑ์Šค(๋ฒ„ํ‚ท)์— ๊ฐ’์„ ์ €์žฅํ•œ๋‹ค.
  • ๋™์ผํ•œ ํ•ด์‹œ ๊ฐ’์ด ๋ฐœ์ƒํ•˜๋ฉด, ํ•ด๋‹น ๋ฒ„ํ‚ท์˜ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ(ํ˜น์€ ํŠธ๋ฆฌ)์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด ์ถฉ๋Œ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

2. Node ํด๋ž˜์Šค

HashMap์˜ ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๊ฐ ํ•ญ๋ชฉ(ํ‚ค-๊ฐ’ ์Œ)์€ Node๋ผ๋Š” ๋‚ด๋ถ€ ํด๋ž˜์Šค๋กœ ํ‘œํ˜„๋œ๋‹ค. Node๋Š” ํ•˜๋‚˜์˜ ํ‚ค-๊ฐ’ ์Œ์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ํ•ด์‹œ ๊ฐ’์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค.

static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;      // ํ‚ค์˜ ํ•ด์‹œ ๊ฐ’
    final K key;         // ํ‚ค
    V value;             // ๊ฐ’
    Node<K,V> next;      // ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฐธ์กฐ(ํ•ด์‹œ ์ถฉ๋Œ ๋ฐœ์ƒ ์‹œ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ)
    
    Node(int hash, K key, V value, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    }

    public final K getKey()        { return key; }
    public final V getValue()      { return value; }
    public final String toString() { return key + "=" + value; }
    public final int hashCode()    { return Objects.hashCode(key) ^ Objects.hashCode(value); }
    public final V setValue(V newValue) {
        V oldValue = value;
        value = newValue;
        return oldValue;
    }
    public final boolean equals(Object o) {
        if (o == this)
            return true;
        if (o instanceof Map.Entry) {
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
            if (Objects.equals(key, e.getKey()) &&
                Objects.equals(value, e.getValue()))
                return true;
        }
        return false;
    }
}

 

  • hash : ํ‚ค์˜ ํ•ด์‹œ ๊ฐ’์œผ๋กœ, ํ•ด์‹œ ํ…Œ์ด๋ธ”์—์„œ ๋ฒ„ํ‚ท์„ ์ฐพ๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  • key : HashMap์— ์ €์žฅ๋œ ํ‚ค
  • value : ํ‚ค์— ๋งคํ•‘๋œ ๊ฐ’
  • next : ๋™์ผํ•œ ํ•ด์‹œ ๊ฐ’์œผ๋กœ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ์˜ ๋‹ค์Œ ๋…ธ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

 

3. ํ•ด์‹œ ํ•จ์ˆ˜์™€ ์ถฉ๋Œ ์ฒ˜๋ฆฌ

1. ํ•ด์‹œ ํ•จ์ˆ˜

HashMap์€ ํ‚ค์˜ ํ•ด์‹œ ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด hashCode() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. hashCode()๋Š” ๊ฐ์ฒด์˜ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋กœ, ์ด ๊ฐ’์€ HashMap์ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฒ„ํ‚ท์— ์ €์žฅํ•  ์œ„์น˜๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

 

ํ•˜์ง€๋งŒ hashCode()๋Š” ๋งค์šฐ ๋‹ค์–‘ํ•œ 32 ๋น„ํŠธ ์ •์ˆ˜ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, HashMap์˜ ์œ ํ•œํ•œํ•œ ๋ฐฐ์—ด ํฌ๊ธฐ์— ํ•œ๊ณ„๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ, ํ•ด์‹œ ๊ฐ’์€ ๋ฐฐ์—ด์˜ ํฌ๊ธฐ์— ๋งž๊ฒŒ ๋น„ํŠธ ์—ฐ์‚ฐ์„ ์กฐ์ •๋œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฒ„ํ‚ท ์ธ๋ฑ์Šค๋ฅผ ๊ตฌํ•œ๋‹ค.

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

 

์ด ๋ฉ”์†Œ๋“œ์€ ํ‚ค์˜ ํ•ด์‹œ ๊ฐ’์„ ๊ณ„์‚ฐํ•œ ํ›„, ํ•ด์‹œ ๊ฐ’์˜ ์ƒ์œ„ ๋น„ํŠธ๋ฅผ ํ•˜์œ„ ๋น„ํŠธ์™€ XOR ์—ฐ์‚ฐํ•ด ํ•ด์‹œ ๊ฐ’์˜ ๋ถ„ํฌ๋ฅผ ๋” ๊ท ์ผํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.

2. ์ถฉ๋Œ ์ฒ˜๋ฆฌ

ํ•ด์‹œ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ, ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ ๋˜๋Š” ํŠธ๋ฆฌ๋ฅด ์‚ฌ์šฉํ•ด ์ถฉ๋Œ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

  • ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ : ๊ฐ™์€ ๋ฒ„ํ‚ท์— ์ €์žฅ๋˜๋Š”  ๋ชจ๋“  ํ•ญ๋ชฉ์€ Node ๊ฐ์ฒด๋กœ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ ํ˜•ํƒœ๋กœ ์ €์žฅ๋œ๋‹ค.
  • ํŠธ๋ฆฌ : ์ž๋ฐ” 8๋ถ€ํ„ฐ, ์ถฉ๋Œ์ด ๋งŽ์ด ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ(๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ๊ฐ€ 8 ์ด์ƒ์ผ ๋•Œ), HashMap์€ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ ๋Œ€์‹  ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ๋กœ ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•ด ํƒ์ƒ‰ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค. ํŠธ๋ฆฌ๋กœ ๋ณ€ํ™˜๋˜๋ฉด ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” O(n)์—์„œ O(log n)์œผ๋กœ ๊ฐœ์„ ๋œ๋‹ค.
if (binCount >= TREEIFY_THRESHOLD - 1) {
    treeifyBin(tab, hash);
}

 

THEEIFY_THRESHOLD๋Š” ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ 9์ด๋‹ค. ๋ฆฌ์ŠคํŠธ๊ฐ€ 8๊ฐœ ์ด์ƒ์˜ ๋…ธ๋“œ๋ฅผ ๊ฐ€์ง€๋ฉด ํŠธ๋ฆฌ๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

 

4. HashMap์˜ ๊ธฐ๋ณธ ๋™์ž‘

1. ๋ฐ์ดํ„ฐ ์‚ฝ์ž… (put ๋ฉ”์†Œ๋“œ)

๋ฐ์ดํ„ฐ๋ฅผ HashMap์— ์‚ฝ์ž…ํ•  ๋•Œ๋Š” ํ‚ค์˜ ํ•ด์‹œ ๊ฐ’์„ ๊ณ„์‚ฐํ•œ ํ›„, ํ•ด๋‹น ํ•ด์‹œ ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฒ„ํ‚ท ์ธ๋ฑ์Šค๋ฅผ ์ฐพ๋Š”๋‹ค. ๋ฒ„ํ‚ท์ด ๋น„์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด, ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•  ๊ฒƒ์ด๋ฏ€๋กœ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋‚˜ ํŠธ๋ฆฌ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฝ์ž…ํ•œ๋‹ค.

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;
    if ((p = tab[i = (n - 1) & hash]) == null)
        tab[i] = newNode(hash, key, value, null);
    else {
        Node<K,V> e; K k;
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        else if (p instanceof TreeNode)
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
            for (int binCount = 0; ; ++binCount) {
                if ((e = p.next) == null) {
                    p.next = newNode(hash, key, value, null);
                    if (binCount >= TREEIFY_THRESHOLD - 1)
                        treeifyBin(tab, hash);
                    break;
                }
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    break;
                p = e;
            }
        }
        if (e != null) { // key already exists
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
        }
    }
    ++modCount;
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
}

 

  • hash(key) : ํ‚ค์˜ ํ•ด์‹œ ๊ฐ’์„ ๊ณ„์‚ฐํ•œ๋‹ค.
  • resize() : ํ…Œ์ด๋ธ”์ด ๊ฝ‰ ์ฐจ๋ฉด ํ•ด์‹œ ํ…Œ์ด๋ธ”์˜ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ฆฐ๋‹ค.
  • treeifyBin() : ์ถฉ๋Œ์ด ๋งŽ์•„์ง€๋ฉด ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋ฅผ ํŠธ๋ฆฌ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

2. ๋ฐ์ดํ„ฐ ์กฐํšŒ (get ๋ฉ”์†Œ๋“œ)

๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ๋„, ํ‚ค์˜ ํ•ด์‹œ ๊ฐ’์„ ๊ณ„์‚ฐํ•˜์—ฌ ํ•ด๋‹น ํ•ด์‹œ ๊ฐ’์— ๋งž๋Š” ๋ฒ„ํ‚ท์—์„œ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ ๋˜๋Š” ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ํƒ์ƒ‰ํ•œ๋‹ค.

public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}

final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
        if (first.hash == hash &&  // check if first node matches
            ((k = first.key) == key || (key != null && key.equals(k))))
            return first;
        if ((e = first.next) != null) {  // check if next nodes match
            if (first instanceof TreeNode)
                return ((TreeNode<K,V>)first).getTreeNode(hash, key);
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;
}

 

ํ‚ค์˜ ํ•ด์‹œ ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด๋‹น ๋ฒ„ํ‚ท์—์„œ ์š”์†Œ๋ฅผ ์ฐพ๋Š”๋‹ค. ๋งŒ์•ฝ ์ถฉ๋„๋กœ์ด ๋ฐœ์ƒํ•˜๋ฉด ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ ๋˜๋Š” ํŠธ๋ฆฌ์—์„œ ํ‚ค๋ฅผ ์ฐพ๋Š”๋‹ค.

 

5. ๋ฆฌํ•ด์‹ฑ๊ณผ ์„ฑ๋Šฅ ์ตœ์ ํ™”

HashMap์€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์•„์ง€๋ฉด ์ž๋™์œผ๋กœ ํ…Œ์ด๋ธ”์˜ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ฆฌ๋Š”๋ฐ, ์ด ๊ณผ์ •์„ ๋ฆฌํ•ด์‹ฑ(rehashing)์ด๋ผ๊ณ  ํ•œ๋‹ค. ํ…Œ์ด๋ธ”์˜ ํฌ๊ธฐ๊ฐ€ 75%๊ฐ€ ์ฐจ๋ฉด resize() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ํฌ๊ธฐ๋ฅผ ๋Š˜๋ฆฌ๊ณ , ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ํ•ด์‹œํ•˜์—ฌ ์ƒˆ๋กœ์šด ํ…Œ์ด๋ธ”์— ์žฌ๋ฐฐ์น˜ํ•œ๋‹ค.

final Node<K,V>[] resize() {
    Node<K,V>[] oldTab = table;
    int oldCap = (oldTab == null) ? 0 : oldTab.length;
    int oldThr = threshold;
    int newCap, newThr = 0;
    if (oldCap > 0) {
        if (oldCap >= MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return oldTab;
        }
        else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                 oldCap >= DEFAULT_INITIAL_CAPACITY)
            newThr = oldThr << 1;
    }
    else if (oldThr > 0)
        newCap = oldThr;
    else {
        newCap = DEFAULT_INITIAL_CAPACITY;
        newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
    }
    if (newThr == 0) {
        float ft = (float)newCap * loadFactor;
        newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                  (int)ft : Integer.MAX_VALUE);
    }
    threshold = newThr;
    @SuppressWarnings({"rawtypes","unchecked"})
    Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
    table = newTab;
    if (oldTab != null) {
        for (int j = 0; j < oldCap; ++j) {
            Node<K,V> e;
            if ((e = oldTab[j]) != null) {
                oldTab[j] = null;
                if (e.next == null)
                    newTab[e.hash & (newCap - 1)] = e;
                else if (e instanceof TreeNode)
                    ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                else {
                    Node<K,V> loHead = null, loTail = null;
                    Node<K,V> hiHead = null, hiTail = null;
                    Node<K,V> next;
                    do {
                        next = e.next;
                        if ((e.hash & oldCap) == 0) {
                            if (loTail == null)
                                loHead = e;
                            else
                                loTail.next = e;
                            loTail = e;
                        }
                        else {
                            if (hiTail == null)
                                hiHead = e;
                            else
                                hiTail.next = e;
                            hiTail = e;
                        }
                    } while ((e = next) != null);
                    if (loTail != null)
                        loTail.next = null;
                    newTab[j] = loHead;
                    if (hiTail != null)
                        hiTail.next = null;
                    newTab[j + oldCap] = hiHead;
                }
            }
        }
    }
    return newTab;
}

 

๊ธฐ๋ณธ์ ์œผ๋กœ ๋‘ ๋ฐฐ๋กœ ํฌ๊ธฐ๋ฅผ ํ™•์žฅํ•˜๋ฉฐ, ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ ํ•ด๋กœ์šด ํ•ด์‹œ ํ…Œ์ด๋ธ”๋กœ ์žฌ๋ฐฐ์น˜ํ•œ๋‹ค.

 

6. ๊ฒฐ๋ก 

HashMap์€ ์ž๋ฐ”์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ ์ค‘ ํ•˜๋‚˜๋กœ, ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋น ๋ฅธ ์„ฑ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค. ํ‚ค์™€ ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด์‹œ ๋ฒ„ํ‚ท์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ , ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•˜๋ฉด ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ ๋˜๋Š” ํŠธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ์„ ์œ ์ง€ํ•œ๋‹ค. HashMap์€ ๋ฆฌํ•ด์‹ฑ์„ ํ†ตํ•ด ๋™์ ์œผ๋กœ ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•˜๋ฉฐ, ์ฃผ์–ด์ง„ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด ๋งค์šฐ ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.