HashTable的使用和原理


一、---使用方式---



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

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

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

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

package ThreeWeek;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

public class HashTableTest {

	public static void main(String args[]){
		Hashtable<String, Integer> table = new Hashtable<String, Integer>();
		
		//[1]添加元素
		table.put("zhangsan", 22);
		table.put("lisi", 33);
		table.put("wangwu", 44);
		
		//[2]toString()方式打印
		System.out.println(table.toString());
		
		//[3]Iterator遍历方式1--键值对遍历entrySet()
		Iterator<Entry<String, Integer>> iter = table.entrySet().iterator();
		while(iter.hasNext()){
			Map.Entry<String, Integer> entry = (Map.Entry<String, Integer>)iter.next();
			String key = entry.getKey();
			int value = entry.getValue();
			System.out.println("entrySet:"+key+" "+value);
		}
		
		System.out.println("====================================");
		
		//[4]Iterator遍历方式2--key键的遍历
		Iterator<String> iterator = table.keySet().iterator();
		while(iterator.hasNext()){
			String key = (String)iterator.next();
			int value = table.get(key);
			System.out.println("keySet:"+key+" "+value);
		}
		
		System.out.println("====================================");
		
		//[5]通过Enumeration来遍历Hashtable
		Enumeration<String> enu = table.keys();
		while(enu.hasMoreElements()) {
		    System.out.println("Enumeration:"+table.keys()+" "+enu.nextElement());
		} 
			
	}
}
--------------------output--------------------

{zhangsan=22, lisi=33, wangwu=44}
entrySet:zhangsan 22
entrySet:lisi 33
entrySet:wangwu 44
====================================
keySet:zhangsan 22
keySet:lisi 33
keySet:wangwu 44
====================================
Enumeration:java.util.Hashtable$Enumerator@139a55 zhangsan
Enumeration:java.util.Hashtable$Enumerator@1db9742 lisi
Enumeration:java.util.Hashtable$Enumerator@106d69c wangwu


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



1、继承关系

java.lang.Object
   ↳     java.util.Dictionary<K, V>
         ↳     java.util.Hashtable<K, V>

public class Hashtable<K,V> extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable { }
与HashMap不同的是Hashtable是继承Dictionary,实现了Map接口。Map是"key-value键值对"接口,Dictionary是声明了操 作"键值对"函数接口的抽象类。 


2、构造函数

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

// 默认构造函数。
public Hashtable() 

// 指定“容量大小”的构造函数
public Hashtable(int initialCapacity) 

// 指定“容量大小”和“加载因子”的构造函数
public Hashtable(int initialCapacity, float loadFactor) 

// 包含“子Map”的构造函数
public Hashtable(Map<? extends K, ? extends V> t)


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

public Hashtable(int initialCapacity, float loadFactor) {  
        //验证初始容量  
        if (initialCapacity < 0)  
            throw new IllegalArgumentException("Illegal Capacity: "+  
                                               initialCapacity);  
        //验证加载因子  
        if (loadFactor <= 0 || Float.isNaN(loadFactor))  
            throw new IllegalArgumentException("Illegal Load: "+loadFactor);  
  
        if (initialCapacity==0)  
            initialCapacity = 1;  
          
        this.loadFactor = loadFactor;  
          
        //初始化table,获得大小为initialCapacity的table数组  
        table = new Entry[initialCapacity];  
        //计算阀值  
        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);  
        //初始化HashSeed值  
        initHashSeedAsNeeded(initialCapacity);  
    }  


3、成员变量

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

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

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

(4)loadFactor就是加载因子。

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

 private transient Entry[] table;
// Hashtable中元素的实际数量
private transient int count;
// 阈值,用于判断是否需要调整Hashtable的容量(threshold = 容量*加载因子)
private int threshold;
// 加载因子
private float loadFactor;
// Hashtable被改变的次数
private transient int modCount = 0;


4、put和get方法

(1)put方法

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

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

public synchronized V put(K key, V value) {  
        // 确保value不为null  
        if (value == null) {  
            throw new NullPointerException();  
        }  
  
        /* 
         * 确保key在table[]是不重复的 
         * 处理过程: 
         * 1、计算key的hash值,确认在table[]中的索引位置 
         * 2、迭代index索引位置,如果该位置处的链表中存在一个一样的key,则替换其value,返回旧值 
         */  
        Entry tab[] = table;  
        int hash = hash(key);    //计算key的hash值  
        int index = (hash & 0x7FFFFFFF) % tab.length;     //确认该key的索引位置  
        //迭代,寻找该key,替换  
        for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {  
            if ((e.hash == hash) && e.key.equals(key)) {  
                V old = e.value;  
                e.value = value;  
                return old;  
            }  
        }  
  
        modCount++;  
        if (count >= threshold) {  //如果容器中的元素数量已经达到阀值,则进行扩容操作  
            rehash();  
            tab = table;  
            hash = hash(key);  
            index = (hash & 0x7FFFFFFF) % tab.length;  
        }  
  
        // 在索引位置处插入一个新的节点  
        Entry<K,V> e = tab[index];  
        tab[index] = new Entry<>(hash, key, value, e);  
        //容器中元素+1  
        count++;  
        return null;  
    }  

(2)get方法

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

public synchronized V get(Object key) {  
        Entry tab[] = table;  
        int hash = hash(key);  
        int index = (hash & 0x7FFFFFFF) % tab.length;  
        for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {  
            if ((e.hash == hash) && e.key.equals(key)) {  
                return e.value;  
            }  
        }  
        return null;  
    }  


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



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两种遍历方式。



尊重作者,尊重原创,参考文章:

http://www.cnblogs.com/skywang12345/p/3310887.html#a1

http://cmsblogs.com/?p=618


### 回答1: Java中的Hashtable是一种基于哈希表的数据结构,用于存储键值对。它的使用方法如下: 1. 创建Hashtable对象: Hashtable<String, Integer> hashtable = new Hashtable<String, Integer>(); 2. 添加键值对: hashtable.put("key1", 1); hashtable.put("key2", 2); hashtable.put("key3", 3); 3. 获取值: int value = hashtable.get("key1"); 4. 判断是否包含某个键: boolean containsKey = hashtable.containsKey("key1"); 5. 判断是否包含某个值: boolean containsValue = hashtable.containsValue(1); 6. 删除键值对: hashtable.remove("key1"); 7. 获取所有键: Enumeration<String> keys = hashtable.keys(); 8. 获取所有值: Enumeration<Integer> values = hashtable.elements(); 注意:Hashtable是线程安全的,但是在多线程环境下,使用ConcurrentHashMap会更好。 ### 回答2: Java Hashtable是一个非常实用的数据结构,因为它可以将键和值的对映射起来,快速地在哈希表中查找和存储数据。要在Java中使用Hashtable,需要知道以下几个方面: 1. 创建Hashtable对象 要创建一个Hashtable对象,应该在Java中使用关键字“new”和Hashtable类名称,并将它们作为构造函数的参数。例如,要创建一个Hashtable对象,代码如下所示: Hashtable<String, String> hashtable = new Hashtable<String, String>(); 注意,这个语句通过使用“String”类型的键和值来创建了一个Hashtable对象。如果不指定键和值的类型,就会得到一个“Object”类型的Hashtable,这可能会导致类型转换问题。 2. 添加键和值 要在Hashtable中添加一个键和值,可以使用“put”方法。这个方法需要一个键和一个值作为参数,并将它们添加到Hashtable中。例如: hashtable.put("key1", "value1"); hashtable.put("key2", "value2"); hashtable.put("key3", "value3"); 3. 获取值 使用“get”方法可以获取Hashtable中的值。这个方法需要一个键作为参数,并返回与该键相关联的值。例如: String value1 = hashtable.get("key1"); String value2 = hashtable.get("key2"); String value3 = hashtable.get("key3"); 4. 删除键和值 要从Hashtable中删除一个键和值,可以使用“remove”方法。这个方法需要一个键作为参数,并删除与该键相关联的键和值。例如: hashtable.remove("key1"); 5. 遍历Hashtable 要遍历Hashtable中的键和值,可以使用“entrySet”和“for”循环。例如: Set<Entry<String, String>> set = hashtable.entrySet(); for (Entry<String, String> entry : set) { String key = entry.getKey(); String value = entry.getValue(); System.out.println("Key: " + key + ", Value: " + value); } 在上面的代码中,首先使用“entrySet”方法获取Hashtable中的所有键和值的集合。然后,循环遍历集合,并使用“getKey”和“getValue”方法获取每个键和值。 总之,Java Hashtable是一个非常实用的数据结构,可以快速地在哈希表中查找和存储数据。要使用Hashtable,需要创建Hashtable对象、添加键和值、获取值、删除键和值以及遍历Hashtable。 ### 回答3: Java Hashtable 是一个基于哈希表实现的 Map 接口,它可用于存储 key-value 键值对,其中每个键都是唯一的。与 HashMap 不同,Hashtable 是线程安全的,它的所有方法都是同步的,因此可以在多线程环境下使用,并且在性能方面与 HashMap 相近。 Java Hashtable 的基本用法如下: 1. 创建 Hashtable 对象: Hashtable<String, String> hashtable = new Hashtable<>(); 其中,"<String, String>" 表示键和值都是字符串类型,也可以使用其他数据类型,如 Integer、Double 等。 2. 添加元素: 添加元素可以使用 put() 方法: hashtable.put("key", "value"); 其中,"key" 表示键,"value" 表示值。 3. 获取元素: 获取元素可以使用 get() 方法: String value = hashtable.get("key"); 其中,"key" 表示键,"value" 表示值。 4. 删除元素: 删除元素可以使用 remove() 方法: hashtable.remove("key"); 其中,"key" 表示键。 5. 遍历元素: 遍历元素可以使用 Enumeration 或者 Iterator: (1)使用 Enumeration 遍历: Enumeration<String> keys = hashtable.keys(); while (keys.hasMoreElements()) { String key = keys.nextElement(); String value = hashtable.get(key); } 其中,keys() 方法返回了一个键的 Enumeration 对象,可以使用 hasMoreElements() 和 nextElement() 方法遍历所有键值对。 (2)使用 Iterator 遍历: Iterator<Map.Entry<String, String>> iterator = hashtable.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, String> entry = iterator.next(); String key = entry.getKey(); String value = entry.getValue(); } 其中,entrySet() 方法返回了一个包含所有键值对的 Set 对象,可以使用 iterator() 方法返回一个迭代器,然后使用 hasNext() 和 next() 方法遍历所有键值对。 以上就是 Java Hashtable 的基本用法,除了以上方法之外,Hashtable 还包含了其它一些重要的方法,如 contains、size() 等,可以根据实际需要使用。注意,在多线程环境下使用 Hashtable 时,需要使用 synchronized 或者 ConcurrentHashMap 等线程安全的集合类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值