자바 기초 - HashTable 소스 코드 분석

14244 단어 자바Hashtable
더 많은 자바 집합 글, 나의 블 로그 에 관심 을 가 져 주세요.http://blog.csdn.net/qq_30379689
자바 기초 - HashTable 소스 코드 분석
이 글 은 다음 과 같은 내용 을 포함 하고 있 습 니 다. 왼쪽 상단 + 번 호 를 클릭 하여 디 렉 터 리 를 펼 치 십시오.
  • Hash Table 이 무엇 입 니까
  • Hashtable 멤버 변수
  • Hashtable 구조 방법
  • Hashtable 저장 소
  • Hashtable 획득
  • Hashtable 스 트 리밍 방식
  • Hashtable 과 HashMap 의 차이
  • 다 중 스 레 드 에 존재 하 는 문제점
  • 1. Hash Table 이 무엇 입 니까?
  • HashTable 은 해시 표 의 Map 인터페이스 동기 화 실현
  • HashTable 에서 요소 의 key 는 유일한 것 이 고 value 값 은 중복 가능
  • HashTable 에 있 는 요소 의 key 와 value 는 null 로 허용 되 지 않 으 며, null 을 만나면 NullPointer Exception
  • 으로 되 돌아 갑 니 다.
  • HashTable 의 요 소 는 무질서 하 다
  • public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable{}

    HashTable 은 HashMap 과 마찬가지 로 링크 산열 의 데이터 구조 입 니 다. 소스 코드 에서 알 수 있 듯 이 Hashtable 은 Dictionary 류 에 계승 되 어 Map, Cloneable, Serializable 인 터 페 이 스 를 실현 합 니 다.
  • Dictionary 류 는 키 를 해당 값 에 투사 할 수 있 는 모든 추상 적 인 부모 류 로 모든 키 와 값 은 대상
  • 이다.
  • Dictionary 소스 코드 주석 은 Dictionary 라 는 유형 이 시대 에 뒤떨어 졌 고 새로운 실현 류 는 Map 인터페이스
  • 를 실현 해 야 한다 고 지적 했다.
    2. Hashtable 멤버 변수
  • table: 하나의 Entry [] 배열 유형 이 고 Entry (HashMap 에서 설명 한 적 이 있 음) 는 단 방향 링크 입 니 다.해시 표 의 "key - value 키 쌍" 은 모두 Entry 배열 에 저 장 된 것 입 니 다
  • count: Hashtable 의 크기, Hashtable 에 저 장 된 키 쌍 의 수량
  • threshold: Hashtable 의 한도 값 은 Hashtable 의 용량 을 조정 해 야 하 는 지 판단 하 는 데 사 용 됩 니 다. threshold 의 값 = (용량 * 부하 인자)
  • loadFactor: 부하 인자
  • modCount: fail - fast 메커니즘 을 실현 하 는 데 사용 되 는
  • 3. Hashtable 구조 방법
    Hashtable 은 모두 4 개의 구조 방법 을 제공 합 니 다.
  • Public Hashtable (int initial Capacity, float loadFactor): 초기 용량 을 지정 하고 로 딩 인 자 를 지정 하여 새로운 빈 해시 표
  • 를 만 듭 니 다.
  • Public Hashtable (int initialCapacity): 초기 용량 과 기본 로드 인자 (0.75) 를 지정 하여 새로운 빈 해시 표
  • 를 만 듭 니 다.
  • Public Hashtable (): 기본 구조 함수, 용량 11, 로드 인자 0.75
  • Public Hashtable (Map t): 주어진 맵 과 같은 맵 관 계 를 가 진 새로운 해시 표
  • 를 구성 합 니 다.
    4. Hashtable 저장 소
    public synchronized V put(K key, V value) {
        //  value  null
        if (value == null) {
            throw new NullPointerException();
        }
    
        //  key  hashtable 
        //  ,  hash    key    ,     index ,    table[]    
        //  ,  index       ,              key,   value,    value
        Entry tab[] = table;
        int hash = hash(key);
        int index = (hash & 0x7FFFFFFF) % tab.length;
        for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                V old = e.value;
                e.value = value;
                return old;
            }
        }
    
        modCount++;
        if (count >= threshold) {
            //      ,   rehash  
            rehash();
    
            tab = table;
            hash = hash(key);
            index = (hash & 0x7FFFFFFF) % tab.length;
        }
    
        //    ,    null
        Entry<K,V> e = tab[index];
        //     Entry  ,    Entry  Hashtable index  ,   e   Entry      
        tab[index] = new Entry<>(hash, key, value, e);
        count++;
        return null;
    }

    저장 프로 세 스 는 다음 과 같 습 니 다.
  • value 가 비어 있 는 지 판단 하고 비어 있 으 면 이상 을 던진다
  • key 의 hash 값 을 계산 하고 hash 값 에 따라 key 가 table 배열 에 있 는 위치 index 를 얻 습 니 다.
  • table [index] 요소 가 비어 있 으 면 table [index] 위치 에 요 소 를 삽입 합 니 다
  • table [index] 요소 가 비어 있 지 않 으 면 링크 를 옮 겨 다 니 며 같은 key 를 만나면 새로운 value 가 오래된 value 를 대체 하고 오래된 value 로 돌아 갑 니 다. 그렇지 않 으 면 요 소 를 체인 헤드 에 삽입 하고 null
  • 로 돌아 갑 니 다.

    5. Hashtable 획득
    public synchronized V get(Object key) {
        Entry tab[] = table;
        int hash = hash(key);
        int index = (hash & 0x7FFFFFFF) % tab.length;
        for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                return e.value;
            }
        }
        return null;
    }

    가 져 오 는 절 차 는 다음 과 같 습 니 다:
  • hash () 방법 을 통 해 key 의 해시 값
  • 을 구 합 니 다.
  • hash 에 따라 index 색인
  • 체인 시트 를 교체 하고 일치 하 는 key 에 대응 하 는 value 를 되 돌려 줍 니 다. 찾 지 못 하면 null
  • 로 돌아 갑 니 다.
    6. Hashtable 스 트 리밍 방식
    Hashtable 은 네 가지 스 트 리밍 방식 이 있 습 니 다.
    //1、  keys()
    Enumeration<String> en1 = table.keys();
        while(en1.hasMoreElements()) {
        en1.nextElement();
    }
    
    //2、  elements()
    Enumeration<String> en2 = table.elements();
        while(en2.hasMoreElements()) {
        en2.nextElement();
    }
    
    //3、  keySet()
    Iterator<String> it1 = table.keySet().iterator();
        while(it1.hasNext()) {
        it1.next();
    }
    
    //4、  entrySet()
    Iterator<Entry<String, String>> it2 = table.entrySet().iterator();
        while(it2.hasNext()) {
        it2.next();
    }

    7. Hashtable 과 HashMap 의 차이
    Hashtable
    HashMap
    방법 은 동기 화 된 것 이다.
    방법 은 비동기 적 이다
    사전 클래스 기반
    추상 맵 기반, 추상 맵 기반 맵 인터페이스 구현
    key 와 value 는 null 로 허용 되 지 않 습 니 다. null 을 만나면 NullPointer Exception 으로 돌아 갑 니 다.
    key 와 value 는 모두 null 로 허용 되 며, key 가 null 일 때 putForNullKey 방법 으로 처리 되 며, value 는 처리 되 지 않 았 습 니 다.
    hash 배열 의 기본 크기 는 11 이 고 확장 방식 은 old * 2 + 1 입 니 다.
    hash 배열 의 기본 크기 는 16 이 고 반드시 2 의 지수 입 니 다.
    8. 다 중 스 레 드 에 존재 하 는 문제점
  • 다 중 스 레 드 동기 화 와 관련 될 경우 HashTable
  • 을 사용 하 는 것 을 권장 합 니 다.
  • 다 중 스 레 드 동기 화 와 관련 이 없 을 때 HashMap
  • 을 사용 하 는 것 을 권장 합 니 다.
  • Collections 클래스 에 정적 인 방법 이 존재 합 니 다. synchronizedMap () 이 방법 은 스 레 드 가 안전 한 Map 대상 을 만 들 고 봉 인 된 대상 으로 되 돌려 줍 니 다
  • synchronizedMap () 은 사실 Map 의 방법 에 동기 화 자 물 쇠 를 더 하 는 것 으로 소스 코드 에서 볼 수 있다.
    //Collections.synchronizedMap(Map<K, V>) 
    public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
         return new SynchronizedMap<K,V>(m);
    }
    
    
    private static class SynchronizedMap<K,V> implements Map<K,V>, Serializable {
        private static final long serialVersionUID = 1978198479659022715L;
    
        private final Map<K,V> m;     // Backing Map
        //   
        final Object      mutex;        // Object on which to synchronize
    
        SynchronizedMap(Map<K,V> m) {
            if (m==null)
                throw new NullPointerException();
            this.m = m;
            // this        ,                     .
            mutex = this;
        }
    
    
        SynchronizedMap(Map<K,V> m, Object mutex) {
            this.m = m;
            this.mutex = mutex;
        }
    
        public int size() {
            synchronized(mutex) {return m.size();}
        }
    
        //  map emty  
        public boolean isEmpty() {
            synchronized(mutex) {return m.isEmpty();}
        }
        public boolean containsKey(Object key) {
            synchronized(mutex) {return m.containsKey(key);}
        }
        public boolean containsValue(Object value) {
            synchronized(mutex) {return m.containsValue(value);}
        }
        public V get(Object key) {
            synchronized(mutex) {return m.get(key);}
        }
    
        public V put(K key, V value) {
            synchronized(mutex) {return m.put(key, value);}
        }
        public V remove(Object key) {
            synchronized(mutex) {return m.remove(key);}
        }
        public void putAll(Map<? extends K, ? extends V> map) {
            synchronized(mutex) {m.putAll(map);}
        }
        public void clear() {
            synchronized(mutex) {m.clear();}
        }
    
        private transient Set<K> keySet = null;
        private transient Set<Map.Entry<K,V>> entrySet = null;
        private transient Collection<V> values = null;
    
        //  keySet  
        public Set<K> keySet() {
            synchronized(mutex) {
                if (keySet==null)
                    //mutex  SynchronizedSet,     set          .
                    keySet = new SynchronizedSet<K>(m.keySet(), mutex);
                return keySet;
            }
        }
    
        public Set<Map.Entry<K,V>> entrySet() {
            synchronized(mutex) {
                if (entrySet==null)
                    entrySet = new SynchronizedSet<Map.Entry<K,V>>(m.entrySet(), mutex);
                return entrySet;
            }
        }
    
        public Collection<V> values() {
            synchronized(mutex) {
                if (values==null)
                    values = new SynchronizedCollection<V>(m.values(), mutex);
                return values;
            }
        }
    
        public boolean equals(Object o) {
            synchronized(mutex) {return m.equals(o);}
        }
        public int hashCode() {
            synchronized(mutex) {return m.hashCode();}
        }
        public String toString() {
            synchronized(mutex) {return m.toString();}
        }
        private void writeObject(ObjectOutputStream s) throws IOException {
            synchronized(mutex) {s.defaultWriteObject();}
        }
    }

    좋은 웹페이지 즐겨찾기