JAVA:hashtable常用方法和原始碼分析
阿新 • • 發佈:2018-12-07
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); } }