Java

예술적인 코드 모음 (계속 업데이트)

OptimizerStart 2025. 4. 29. 15:28

주관적입니다.

HashMap 클래스의 put() 메서드의 구현부 

 

  • 목적 : 튜닝. Hash 자료구조는 O(1) 성능을 목표로함. 읽고 쓰기가 빈번한 작업을 최소화할 필요있음
  • 방법 : 인스턴스 변수 읽기(접근) 1번으로 줄임.
    • 인스턴스 변수 접근 최소화하기 위해 바로 로컬 변수 (tab)에 대입.
    • 조건식을 항상 검사하므로, tab 에 table 참조변수에 저장된 주소가 대입됨. 

 

  • 첫 의문증 : 왜 대입문을 if문 조건식 내부에 작성했나? 밖에 있으면 안되나? 

 

실제 Key와 Value를 저장하는 1차원 배열과 링크드 리스트로 구성된 객체 자체를 가리키기 위해 putVal() 메서드 내부에서 tab에 table 참조변수에 저장된 주소를 대입해야한다. 근데 코드 봤는데 'tab = table' 대입문이 없었다. 자세히 보니 if문 조건식 내부에 대입문을 작성해서 if문 바깥으로 대입문을 작성하지 않아도 그 아래 모든 코드 영역에 tab = table; 인 상태가 유지된다. 

처음으로 코드가 예술적이라 느꼈다. 

if ((tab = table) == null || (n = tab.length) == 0)

4번 줄 위치

 

putVal() 구현부 

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) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

 

put()의 구현부 

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