HASHTABLE的内部实现

public   class  TestHashtable  {
    
public   static   void  main(String[] args) {
        Hashtable ht 
=   new  Hashtable();
        ht.put(
" sichuan " , " chengdu " );  // 改变以下四行代码的顺序,可能会改变输出内容的顺序    
        ht.put( " hunan " , " changsha " );     
        ht.put(
" beijing " , " beijing " );    
        ht.put(
" anhui " , " hefei " );    
        
    Enumeration e 
=  ht.keys();
    
while (e.hasMoreElements())  {
        Object key 
=  e.nextElement();
        Object value 
=  ht.get(key);            
        System.out.println(key 
+   "   "   +  value  +   "   "   +  key.hashCode()  +   "   "   +  value.hashCode());
    }

        
    }

}

 为了讲述Hashtable键排序的问题,我们先来看Hashtable的结构图:

Hashtable.GIF

        从上面的结构图可以看出,Hashtable的实质就是一个数组+链表。图中的Entry就是链表的实现,Entry的结构中包含了对自己的另一个实例的引用next,用以指向另外一个Entry。而图中标有数字的部分是一个Entry数组,数字就是这 个Entry数组的index。那么往Hashtable增加键值对的时候,index会根据键的hashcode、Entry数组的长度共同决定,从而决定键值对存放在Entry数组的哪个位置。从这 种意义来说,当键一定,Entry数组的长度一定的情况下,所得到的index肯定是相同的,也就是说插入顺序应该不会影响输出 的顺序才对。然而,还有一个重要的因素没有考虑,就是计算index出现相同值的情况。譬如代码中 "sichuan" 和 "anhui",所 得到的index是相同的,在这个时候,Entry的链表功能就发挥作用了:put方法通过Entry的next属性获得对另外一个Entry的 引用,然后将后来者放入其中。根据debug得出的结果,"sichuan", "anhui"的index同为2,"hunan"的index为6," beijing"的index为1,在输出的时候,会以index递减的方式获得键值对。很明显,会改变的输出顺序只有"sichuan"和" anhui"了,也就是说输出只有两种可能:"hunan" - "sichuan" - "anhui" - "beijing"和"hunan" - "anhui" - " sichuan" - "beijing"。以下是运行了示例代码之后,Hashtable的结果:

Hashtable1.GIF

    
        以上的讨论基于Java展开的,在C#中的Hashtable实现会有所不同,但是我相信两者的设计应该是差不多的。感谢叶漂
和quitgame,给了我思考的机会,也让我感到了基础知识的匮乏,看来是要补补基础知识了。   

        [补充]:在Hashtable的实现代码中,有一个名为rehash的方法用于扩充Hashtable的容量。很明显,当rehash方法被调用
以后,每一个键值对相应的index也会改变,也就等于将键值对重新排序了。这也是往不同容量的Hashtable放入相同的键值对 会输出不同的键值对序列的原因。在Java中,触发rehash方法的条件很简单:hahtable中的键值对超过某一阀值。默认情况下 ,该阀值等于hashtable中Entry数组的长度×0.75

http://www.blogjava.net/csusky/archive/2008/02/19/180613.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章