Hashtable源码分析

来源:互联网 发布:linux imp导入dmp文件 编辑:程序博客网 时间:2024/05/29 18:12

出处:http://zy19982004.iteye.com/blog/1662578

一.前言

  1. HashMap和Hashtable大部分算法是相同的,容器学习一:HashMap源码分析 对HashMap源码进行了分析,可以先阅读它。
  2. 相同的算法部分不再分析,本文主要考虑Hashtable和HashMap的不同之处。

 

二.Hashtable成员变量

Java代码  收藏代码
  1. private transient Entry[] table;  
  2.   
  3. // 等同于HashMap里面的size  
  4. private transient int count;  
  5.   
  6. private int threshold;  
  7.   
  8. private float loadFactor;  
  9.   
  10. private transient int modCount = 0;  

 

 

 

三.Hashtable构造函数

Java代码  收藏代码
  1. // DEFAULT_INITIAL_CAPACITY=11,DEFAULT_LOAD_FACTOR还是0.75  
  2. public Hashtable() {  
  3.     this(110.75f);  
  4. }  
  5.   
  6. public Hashtable(int initialCapacity, float loadFactor) {  
  7.     if (initialCapacity < 0)  
  8.         throw new IllegalArgumentException("Illegal Capacity: "  
  9.                 + initialCapacity);  
  10.     if (loadFactor <= 0 || Float.isNaN(loadFactor))  
  11.         throw new IllegalArgumentException("Illegal Load: " + loadFactor);  
  12.   
  13.     if (initialCapacity == 0)  
  14.         initialCapacity = 1;  
  15.     // 直接用initialCapacity初始化,并没有要求用2的次方指来初始化  
  16.     this.loadFactor = loadFactor;  
  17.     table = new Entry[initialCapacity];  
  18.     threshold = (int) (initialCapacity * loadFactor);  
  19. }  

 

 

四.hash算法和index算法

Java代码  收藏代码
  1. //自己拿到key的hash值  
  2. int hash = key.hashCode();  
  3. //计算index做了求模运算。  
  4. int index = (hash & 0x7FFFFFFF) % tab.length;  

 

 

五.取数据

Java代码  收藏代码
  1. public synchronized V get(Object key) {  
  2.     Entry tab[] = table;  
  3.     //Hashtable所有的方法都不接受null的key,所有的地方都是不判断就直接key.hashCode();  
  4.     int hash = key.hashCode();         
  5.     int index = (hash & 0x7FFFFFFF) % tab.length;  
  6.     for (Entry<K, V> e = tab[index]; e != null; e = e.next) {  
  7.         //同HahsMap相比没有判断e.key==key,  
  8.         //Hahstable里面,e.key.equals(key)就够了,在key不为null的前提下e.key==key是e.key.equals(key)的充分不必要条件  
  9.         if ((e.hash == hash) && e.key.equals(key)) {   
  10.             return e.value;  
  11.         }  
  12.     }  
  13.     return null;  
  14. }  

 

 

六.存数据

Java代码  收藏代码
  1. public synchronized V put(K key, V value) {  
  2.         if (value == null) {  
  3.             throw new NullPointerException();  
  4.         }  
  5.   
  6.         Entry tab[] = table;  
  7.         int hash = key.hashCode();  
  8.         int index = (hash & 0x7FFFFFFF) % tab.length;  
  9.         for (Entry<K, V> e = tab[index]; e != null; e = e.next) {  
  10.             if ((e.hash == hash) && e.key.equals(key)) {  
  11.                 V old = e.value;  
  12.                 e.value = value;  
  13.                 return old;  
  14.             }  
  15.         }  
  16.   
  17.         modCount++;  
  18.         //HashMap先加Entry再决定是否扩容,Hahstable再判断大小在加Entry  
  19.         //我还是喜欢这样比较:count + 1 >  threshold  
  20.         if (count >= threshold) {  
  21.             rehash();  
  22.   
  23.             tab = table;  
  24.             index = (hash & 0x7FFFFFFF) % tab.length;  
  25.         }  
  26.   
  27.         // Creates the new entry.  
  28.         Entry<K, V> e = tab[index];  
  29.         tab[index] = new Entry<K, V>(hash, key, value, e);  
  30.         count++;  
  31.         return null;  
  32.     }  
  33.       
  34.     protected void rehash() {  
  35.         int oldCapacity = table.length;  
  36.         Entry[] oldMap = table;  
  37.   
  38.         int newCapacity = oldCapacity * 2 + 1;  
  39.         Entry[] newMap = new Entry[newCapacity];  
  40.   
  41.         modCount++;  
  42.         threshold = (int) (newCapacity * loadFactor);  
  43.         table = newMap;  
  44.                 //和HashMap算法是一样的,建议看HashMap里面的写法好理解点。  
  45.         for (int i = oldCapacity; i-- > 0;) {  
  46.             for (Entry<K, V> old = oldMap[i]; old != null;) {  
  47.                 Entry<K, V> e = old;  
  48.                 old = old.next;  
  49.   
  50.                 int index = (e.hash & 0x7FFFFFFF) % newCapacity;  
  51.                 e.next = newMap[index];  
  52.                 newMap[index] = e;  
  53.             }  
  54.         }  
  55.     }  

 

 

七.总结

 

 HashMapHashtable出现时间JDK1.2,所以代码质量更高,更容易明白JDK1.0并发控制没有考虑并发所有方法都加了synchronized,即使有些我认为不需要的也加了
是否接受值为null的Key 或Value
接受不接收。put等方法里面:if (value == null) {
            显示throw new NullPointerException();
        };int hash=key.hashcode隐示throw NullPointerException();初始化table缺省容量16。初始化时可以指定initial capacity,若不是2的次方,HashMap将选取第一个大于initial capacity 的2的次方值作为其初始长度缺省容量11。初始化时可以指定initial capacity扩容添加Entry后判断是否该扩容。扩容至2*oldCapacity先判断是否扩容再添加Entry。扩容至2*oldCapacity + 1数据遍历的方式Iterator
Iterator 和 Enumeration
是否支持fast-fail
支持fast-fail
用Iterator遍历,支持fast-fail
用Enumeration不支持fast-fail.
hash算法和index算法
优于Hashtable,通过对Key的hash做移位运算和位的与运算,使其能更广泛地分散到数组的不同位置
当数组长度较小,并且Key的hash值低位数值分散不均匀时,不同的hash值计算得到相同下标值的几率较高
实现和继承extends AbstractMap 骨架结构的体现,代码质量上去了extends Dictionary implements Map 直接实现Map接口。多基础了一个已过时的经Dictionary类,就不用去管了


0 0