1. 程式人生 > >JAVA:hashtable常用方法和原始碼分析

JAVA:hashtable常用方法和原始碼分析

 public  static void main(String[] args) {

        Hashtable<String,Integer> hashtable=new Hashtable<String, Integer>();
        
        /**hashtable底層資料結構:陣列+連結串列
         * 不能儲存Null值
         * 不能保證插入有序
         * 執行緒安全
         * 增加元素,陣列擴容方式為2倍+1的方式,初始容量為11
         *  繼承Dictionary<K,V>類,提供了特有的遍歷方式(列舉遍歷Enumeration:)其中有
         *  boolean hasMoreElements()和E nextElement()方法,在hashtable中呼叫使用elements()方法呼叫
         *  同時實現implements Map<K,V>, Cloneable, java.io.Serializable介面
         */
         hashtable.put("ls",18);//插入元素
         hashtable.put("zs",19);
         //put原始碼分析:
        /**初始容量和載入因子
         *  public Hashtable() {
         *         this(11, 0.75f);
         *     }
         *  public synchronized V put(K key, V value) {
         *         if (value == null) {//           1.說明value值不能為null
         *             throw new NullPointerException();
         *         }
         *         Entry<?,?> tab[] = table;
         *         int hash = key.hashCode();//計算雜湊值,此處說明value值不能為null,否則會出現空指標異常
         *         int index = (hash & 0x7FFFFFFF) % tab.length;//計算位置
         *         Entry<K , V> entry = (Entry<K,V>)tab[index];
         *         for(; entry != null ; entry = entry.next) {//遍歷查詢是否插入的新元素和舊元素hash值和key值相等,
         *          如果相等用新的value替換舊的value,並返回舊的value,否則跳出for迴圈。直接插入元素
         *         
         *             if ((entry.hash == hash) && entry.key.equals(key)) {
         *                 V old = entry.value;
         *                 entry.value = value;
         *                 return old;
         *             }
         *         }
         *
         *         addEntry(hash, key, value, index);//存在擴容機制
         *         return null;
         *     }
         *     //新增元素addEntry
         *       private void addEntry(int hash, K key, V value, int index) {
         *         modCount++;
         *         Entry<?,?> tab[] = table;
         *         if (count >= threshold) {
         *         如果大於閾值需要重雜湊,
         *             rehash();
         *
         *             tab = table;
         *             hash = key.hashCode();
         *             index = (hash & 0x7FFFFFFF) % tab.length;//與hashmap的計算雜湊位置不同
         *         }
         *         Entry<K , V> e = (Entry<K,V>) tab[index];
         *         tab[index] = new Entry<>(hash, key, value, e);
         *         count++;
         *     }
         *     重雜湊
         *  protected void rehash() {
         *         int oldCapacity = table.length;
         *         Entry<?,?>[] oldMap = table;
         *         int newCapacity = (oldCapacity << 1) + 1;//2倍+1的方式擴容陣列
         *         if (newCapacity - MAX_ARRAY_SIZE > 0) {
         *             if (oldCapacity == MAX_ARRAY_SIZE)
         *                 return;
         *             newCapacity = MAX_ARRAY_SIZE;
         *         }
         *         Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
         *
         *         modCount++;
         *         //重新計算閾值:新的容量*載入因子和最大值+1中最小的值,閾值的作用顯然實在新增元素是判斷是否擴容陣列發揮作用
         *         threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
         *         table = newMap;
         *          //將舊的元素通過for迴圈放入新的陣列
         *         for (int i = oldCapacity ; i-- > 0 ;) {
         *             for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
         *                 Entry<K,V> e = old;
         *                 old = old.next;
         *
         *                 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
         *                 e.next = (Entry<K,V>)newMap[index];
         *                 newMap[index] = e;
         *             }
         *         }
         *     }
         *     
         *
         */
         hashtable.remove("ls");
        /**
         * 刪除元素:
         * 1.計算雜湊值
         * 2.通過雜湊值找位置
         * 3.通過位置找節點,遍歷整個連結串列,如果存在,根據連結串列的刪除元素的方法刪除即可,
         * 最後需要將value值賦值為null,避免記憶體洩漏
         * 
         * 
         *  public synchronized V remove(Object key) {
         *         Entry<?,?> tab[] = table;
         *         int hash = key.hashCode();
         *         int index = (hash & 0x7FFFFFFF) % tab.length;
         *         Entry<K , V> e = (Entry<K,V>)tab[index];
         *         for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {
         *             if ((e.hash == hash) && e.key.equals(key)) {
         *                 modCount++;
         *                 if (prev != null) {
         *                     prev.next = e.next;
         *                 } else {
         *                     tab[index] = e.next;
         *                 }
         *                 count--;
         *                 V oldValue = e.value;
         *                 e.value = null;
         *                 return oldValue;
         *             }
         *         }
         *         return null;
         *     }
         *
         */
        Integer ls = hashtable.get("ls");
        /**
         * 通過鍵獲取元素,也是:
         * 1.計算雜湊值
         * 2.通過雜湊函式計算位置
         * 3.遍歷查詢,返回value
         *  public synchronized V get(Object key) {
         *         Entry<?,?> tab[] = table;
         *         int hash = key.hashCode();
         *         int index = (hash & 0x7FFFFFFF) % tab.length;
         *         for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
         *             if ((e.hash == hash) && e.key.equals(key)) {
         *                 return (V)e.value;
         *             }
         *         }
         *         return null;
         *     }
         *
         */
        hashtable.contains("ls");
        /**
         * 
         *  public synchronized boolean contains(Object value) {
         *         if (value == null) {
         *             throw new NullPointerException();//value值不能為null
         *         }
         *         Entry<?,?> tab[] = table;
         *         for (int i = tab.length ; i-- > 0 ;) {//倒著遍歷陣列
         *             for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {//遍歷每個陣列每個位置的連結串列
         *                 if (e.value.equals(value)) {
         *                     return true;
         *                 }
         *             }
         *         }
         *         return false;
         *     }
         */
        


        /**
         * 
         * 遍歷方式有四種,如下
         */
        //使用列舉的方法遍歷
        Enumeration<Integer> elements = hashtable.elements();
        while (elements.hasMoreElements()){
            Integer integer = elements.nextElement();
            System.out.println(integer);
        }
        //節點的方式遍歷
        Set<Map.Entry<String, Integer>> entries = hashtable.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Integer> next = iterator.next();
            System.out.println(next.getValue());
        }
        //key遍歷
        Set<String> strings = hashtable.keySet();
        Iterator<String> iterator1 = strings.iterator();
        while (iterator1.hasNext()){
            String next = iterator1.next();
            System.out.println(next);
        }
        //value值遍歷
        Collection<Integer> values = hashtable.values();
        Iterator<Integer> iterator2 = values.iterator();
        while (iterator2.hasNext()){
            Integer next = iterator2.next();
            System.out.println(next);
        }
       

    }