Java中的集合(十三) 实现Map接口的Hashtable

Java中的集合(十三) 实现Map接口的Hashtable

一、Hashtable简介

和HashMap一样,Hashtable采用“拉链法”实现一个哈希表,它存储的内容是键值对(key-value)映射。Hashtable 的实例有两个参数影响其性能:初始容量 (11)和 加载因子(0.75)。容量 是哈希表中桶 的数量,初始容量 就是哈希表创建时的容量。注意,哈希表的状态为 open:在发生“哈希冲突”的情况下,单个桶会存储多个条目,这些条目必须按顺序搜索。加载因子 是对哈希表在其容量自动增加之前可以达到多满的一个尺度。初始容量和加载因子这两个参数只是对该实现的提示。关于何时以及是否调用 rehash 方法的具体细节则依赖于该实现。
通常,默认加载因子是 0.75, 这是在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查找某个条目的时间(在大多数 Hashtable 操作中,包括 get 和 put 操作,都反映了这一点)。

(一)、Hashtable与Map接口的关系

二、Hashtable的继承结构

Hashtable继承Dictionary,实现了Map、Cloneable和Serializable接口。Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。此外,Hashtable中的映射不是有序的。

三、Hashtable的构造方法

四、Hashtable主要成员属性

Hashtable采用"拉链法"实现哈希表,它定义了几个重要的参数:table、count、threshold、loadFactor、modCount。

1、table

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

2、count

是Hashtable的大小,它是Hashtable保存的键值对的数量。

3、threshold

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

4、loadFactor

加载因子,默认为0.75。

5、modCount

是用来实现fail-fast机制的。

五、Hashtable的遍历方式

(一)、迭代器的遍历方式

Hashtable的迭代器遍历方式和HashMap的基本一致,可参考Java集合(十)实现Map接口的HashMap 的遍历方式。

(二)、Enumeration(枚举器)遍历

1、通过Enumeration遍历Hashtable的键

①、通过keys方法获得Enumeration<K>枚举器集合

②、通过Enumeration遍历

 

1 // 假设Hashtable的键为String类型,值为Integer类型
2 Hashtable<String,Integer> table = new Hashtable<String,Integer>();
3 Enumeration<String> enu =  table.keys();
4 while(enu.hasMoreElements()) {
5     String str = enu.nextElement();
6 }
View Code

 

 

 

2、通过Enumeration遍历Hashtable的值

①、通过elements方法Enumeration<K>枚举器集合

②、通过Enumeration遍历

 

1 Enumeration<Integer> enu =  table.elements();
2 while(enu.hasMoreElements()) {
3     Integer i = enu.nextElement();
4 }
View Code

 

 

 

六、Hashtable常用API

七、Hashtable与HashMap的异同

(一)、相同点

1、HashMap和Hashtable都是存储“键值对(key-value)”的散列表,而且都是采用拉链法实现的。

存储的思想都是:通过table数组存储,数组的每一个元素都是一个Entry;而一个Entry就是一个单向链表,Entry链表中的每一个节点就保存了key-value键值对数据。

①、添加key-value键值对:首先,根据key值计算出哈希值,再计算出数组索引(即,该key-value在table中的索引)。然后,根据数组索引找到Entry(即,单向链表),再遍历单向链表,将key和链表中的每一个节点的key进行对比。若key已经存在Entry链表中,则用该value值取代旧的value值;若key不存在Entry链表中,则新建一个key-value节点,并将该节点插入Entry链表的表头位置。

②、删除key-value键值对:删除键值对,相比于“添加键值对”来说,简单很多。首先,还是根据key计算出哈希值,再计算出数组索引(即,该key-value在table中的索引)。然后,根据索引找出Entry(即,单向链表)。若节点key-value存在与链表Entry中,则删除链表中的节点即可。

2、加载因子都是0.75。

(二)、不同点

1、继承方式不同。

HashMap继承AbstractMap,Hashtable继承Dictionary,但是同样实现了Map、Cloneable、java.io.Serializable接口。

2、线程安全不同。

HashMap是非同步,线程不安全的;Hashtable是同步到,线程安全的。

3、存储null处理方式。

HashMap的键值都可以为null,Hashtable的键值都不可以为null。

4、遍历方式不同。

HashMap只支持获取迭代器遍历;Hashtable支持Iterator(迭代器)和Enumeration(枚举器)两种方式遍历。

5、容量的初始值不同。

HashMap初始值默认为16;Hashtable默认为11。

6、增加方式不同。

当HashMap的 “实际容量” >= “阈值”时,(阈值 = 总的容量 * 加载因子),就将HashMap的容量翻倍;

Hashtable的 “实际容量” >= “阈值”时,(阈值 = 总的容量 x 加载因子),就将变为“原始容量x2 + 1”。

7、添加key-value时的hash值计算方式不同。

HashMap添加kley-value时,采用的是自定义的哈希算法计算hash值;

Hashtable没有自定义哈希算法,而是采用key的hashCode(当自定义对象是必须重写hashCode和equals方法)。

posted @ 2020-05-15 00:21  凌倾-学无止境  阅读(626)  评论(0编辑  收藏  举报