HashTable如何应用及原理

(1)Hashtable 是一个散列表,它存储的内容是键值对(key-value)映射。

(2)Hashtable 继承于Dictionary,实现了Map、Cloneable、java.io.Serializable接口。

(3)Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。

如下是Hashtable 的简单使用方式:在遍历时使用是三种遍历方式来对其进行遍历

[java]  view plain  copy
  1. package ThreeWeek;  
  2.   
  3. import java.util.Enumeration;  
  4. import java.util.Hashtable;  
  5. import java.util.Iterator;  
  6. import java.util.Map;  
  7. import java.util.Map.Entry;  
  8.   
  9. public class HashTableTest {  
  10.   
  11.     public static void main(String args[]){  
  12.         Hashtable<String, Integer> table = new Hashtable<String, Integer>();  
  13.           
  14.         //[1]添加元素  
  15.         table.put("zhangsan"22);  
  16.         table.put("lisi"33);  
  17.         table.put("wangwu"44);  
  18.           
  19.         //[2]toString()方式打印  
  20.         System.out.println(table.toString());  
  21.           
  22.         //[3]Iterator遍历方式1--键值对遍历entrySet()  
  23.         Iterator<Entry<String, Integer>> iter = table.entrySet().iterator();  
  24.         while(iter.hasNext()){  
  25.             Map.Entry<String, Integer> entry = (Map.Entry<String, Integer>)iter.next();  
  26.             String key = entry.getKey();  
  27.             int value = entry.getValue();  
  28.             System.out.println("entrySet:"+key+" "+value);  
  29.         }  
  30.           
  31.         System.out.println("====================================");  
  32.           
  33.         //[4]Iterator遍历方式2--key键的遍历  
  34.         Iterator<String> iterator = table.keySet().iterator();  
  35.         while(iterator.hasNext()){  
  36.             String key = (String)iterator.next();  
  37.             int value = table.get(key);  
  38.             System.out.println("keySet:"+key+" "+value);  
  39.         }  
  40.           
  41.         System.out.println("====================================");  
  42.           
  43.         //[5]通过Enumeration来遍历Hashtable  
  44.         Enumeration<String> enu = table.keys();  
  45.         while(enu.hasMoreElements()) {  
  46.             System.out.println("Enumeration:"+table.keys()+" "+enu.nextElement());  
  47.         }   
  48.               
  49.     }  
  50. }  
--------------------output--------------------

[java]  view plain  copy
  1. {zhangsan=22, lisi=33, wangwu=44}  
  2. entrySet:zhangsan 22  
  3. entrySet:lisi 33  
  4. entrySet:wangwu 44  
  5. ====================================  
  6. keySet:zhangsan 22  
  7. keySet:lisi 33  
  8. keySet:wangwu 44  
  9. ====================================  
  10. Enumeration:java.util.Hashtable$Enumerator@139a55 zhangsan  
  11. Enumeration:java.util.Hashtable$Enumerator@1db9742 lisi  
  12. Enumeration:java.util.Hashtable$Enumerator@106d69c wangwu  


二、---内部原理---



1、继承关系

[java]  view plain  copy
  1. java.lang.Object  
  2.    ↳     java.util.Dictionary<K, V>  
  3.          ↳     java.util.Hashtable<K, V>  
  4.   
  5. public class Hashtable<K,V> extends Dictionary<K,V>  
  6.     implements Map<K,V>, Cloneable, java.io.Serializable { }  
与HashMap不同的是Hashtable是继承Dictionary,实现了Map接口。Map是"key-value键值对"接口,Dictionary是声明了操 作"键值对"函数接口的抽象类。 


2、构造函数

(1)Hashtable中提供了四个构造函数,如下:

[java]  view plain  copy
  1. // 默认构造函数。  
  2. public Hashtable()   
  3.   
  4. // 指定“容量大小”的构造函数  
  5. public Hashtable(int initialCapacity)   
  6.   
  7. // 指定“容量大小”和“加载因子”的构造函数  
  8. public Hashtable(int initialCapacity, float loadFactor)   
  9.   
  10. // 包含“子Map”的构造函数  
  11. public Hashtable(Map<? extends K, ? extends V> t)  


(2)上面的四个构造方法中,第三个是最重要的,指定初始化容量和构造因子

[java]  view plain  copy
  1. public Hashtable(int initialCapacity, float loadFactor) {    
  2.         //验证初始容量    
  3.         if (initialCapacity < 0)    
  4.             throw new IllegalArgumentException("Illegal Capacity: "+    
  5.                                                initialCapacity);    
  6.         //验证加载因子    
  7.         if (loadFactor <= 0 || Float.isNaN(loadFactor))    
  8.             throw new IllegalArgumentException("Illegal Load: "+loadFactor);    
  9.     
  10.         if (initialCapacity==0)    
  11.             initialCapacity = 1;    
  12.             
  13.         this.loadFactor = loadFactor;    
  14.             
  15.         //初始化table,获得大小为initialCapacity的table数组    
  16.         table = new Entry[initialCapacity];    
  17.         //计算阀值    
  18.         threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);    
  19.         //初始化HashSeed值    
  20.         initHashSeedAsNeeded(initialCapacity);    
  21.     }    


3、成员变量

(1)table是一个Entry[]数组类型,而Entry实际上就是一个单向链表。哈希表的"key-value键值对"都是存储在Entry数组中的。 

(2)count是Hashtable的大小,它是Hashtable保存的键值对的数量。 

(3)threshold是Hashtable的阈值,用于判断是否需要调整Hashtable的容量。threshold的值="容量*加载因子"。

(4)loadFactor就是加载因子。

(5)modCount是用来实现fail-fast机制的

[java]  view plain  copy
  1.  private transient Entry[] table;  
  2. // Hashtable中元素的实际数量  
  3. private transient int count;  
  4. // 阈值,用于判断是否需要调整Hashtable的容量(threshold = 容量*加载因子)  
  5. private int threshold;  
  6. // 加载因子  
  7. private float loadFactor;  
  8. // Hashtable被改变的次数  
  9. private transient int modCount = 0;  


4、put和get方法

(1)put方法

从下面的代码中我们可以看出,Hashtable中的key和value是不允许为空的,当我们想要想Hashtable中添加元素的时候,首先计算key的hash值,然

后通过hash值确定在table数组中的索引位置,最后将value值替换或者插入新的元素,如果容器的数量达到阈值,就会进行扩充。

[java]  view plain  copy
  1. public synchronized V put(K key, V value) {    
  2.         // 确保value不为null    
  3.         if (value == null) {    
  4.             throw new NullPointerException();    
  5.         }    
  6.     
  7.         /*  
  8.          * 确保key在table[]是不重复的  
  9.          * 处理过程:  
  10.          * 1、计算key的hash值,确认在table[]中的索引位置  
  11.          * 2、迭代index索引位置,如果该位置处的链表中存在一个一样的key,则替换其value,返回旧值  
  12.          */    
  13.         Entry tab[] = table;    
  14.         int hash = hash(key);    //计算key的hash值    
  15.         int index = (hash & 0x7FFFFFFF) % tab.length;     //确认该key的索引位置    
  16.         //迭代,寻找该key,替换    
  17.         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {    
  18.             if ((e.hash == hash) && e.key.equals(key)) {    
  19.                 V old = e.value;    
  20.                 e.value = value;    
  21.                 return old;    
  22.             }    
  23.         }    
  24.     
  25.         modCount++;    
  26.         if (count >= threshold) {  //如果容器中的元素数量已经达到阀值,则进行扩容操作    
  27.             rehash();    
  28.             tab = table;    
  29.             hash = hash(key);    
  30.             index = (hash & 0x7FFFFFFF) % tab.length;    
  31.         }    
  32.     
  33.         // 在索引位置处插入一个新的节点    
  34.         Entry<K,V> e = tab[index];    
  35.         tab[index] = new Entry<>(hash, key, value, e);    
  36.         //容器中元素+1    
  37.         count++;    
  38.         return null;    
  39.     }    

(2)get方法

同样也是先获得索引值,然后进行遍历,最后返回

[java]  view plain  copy
  1. public synchronized V get(Object key) {    
  2.         Entry tab[] = table;    
  3.         int hash = hash(key);    
  4.         int index = (hash & 0x7FFFFFFF) % tab.length;    
  5.         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {    
  6.             if ((e.hash == hash) && e.key.equals(key)) {    
  7.                 return e.value;    
  8.             }    
  9.         }    
  10.         return null;    
  11.     }    


五、---比较不同---



Hashtable和HashMap到底有哪些不同呢

(1)基类不同:HashTable基于Dictionary类,而HashMap是基于AbstractMap。Dictionary是什么?它是任何可将键映射到相应值的类的抽象父类,而AbstractMap是基于Map接口的骨干实现,它以最大限度地减少实现此接口所需的工作。

(2)null不同:HashMap可以允许存在一个为null的key和任意个为null的value,但是HashTable中的key和value都不允许为null。

(3)线程安全:HashMap时单线程安全的,Hashtable是多线程安全的。

(4)遍历不同:HashMap仅支持Iterator的遍历方式,Hashtable支持Iterator和Enumeration两种遍历方式。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值