您的位置:首页 > 编程语言 > Java开发

java1.8 过时集合源码学习:Hashtable

2017-10-28 16:27 239 查看
1、api

此类实现一个哈希表,该哈希表将键映射到相应的值。任何非 null 对象都可以用作键或值。
为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode 方法和 equals 方法。
Hashtable 的实例有两个参数影响其性能:初始容量 和加载因子。容量 是哈希表中桶 的数量,初始容量 就是哈希表创建时的容量。注意,哈希表的状态为 open:在发生“哈希冲突”的情况下,单个桶会存储多个条目,这些条目必须按顺序搜索。加载因子 是对哈希表在其容量自动增加之前可以达到多满的一个尺度。初始容量和加载因子这两个参数只是对该实现的提示。关于何时以及是否调用
rehash 方法的具体细节则依赖于该实现。
通常,默认加载因子(.75)在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查找某个条目的时间(在大多数 Hashtable 操作中,包括 get 和 put 操作,都反映了这一点)。
初始容量主要控制空间消耗与执行 rehash 操作所需要的时间损耗之间的平衡。如果初始容量大于 Hashtable 所包含的最大条目数除以加载因子,则永远不会发生 rehash 操作。但是,将初始容量设置太高可能会浪费空间。
如果很多条目要存储在一个 Hashtable 中,那么与根据需要执行自动 rehashing 操作来增大表的容量的做法相比,使用足够大的初始容量创建哈希表或许可以更有效地插入条目。
下面这个示例创建了一个数字的哈希表。它将数字的名称用作键:
Hashtable<String, Integer> numbers = new Hashtable<String, Integer>(); numbers.put("one", 1); numbers.put("two", 2); numbers.put("three", 3);
要获取一个数字,可以使用以下代码:
Integer n = numbers.get("two"); if (n != null) { System.out.println("two = " + n); }
}
由所有类的“collection 视图方法”返回的 collection 的 iterator 方法返回的迭代器都是快速失败 的:在创建
Iterator 之后,如果从结构上对 Hashtable 进行修改,除非通过 Iterator 自身的 remove 方法,否则在任何时间以任何方式对其进行修改,Iterator 都将抛出ConcurrentModificationException。因此,面对并发的修改,Iterator
很快就会完全失败,而不冒在将来某个不确定的时间发生任意不确定行为的风险。由 Hashtable 的键和元素方法返回的 Enumeration 不 是快速失败的。
注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误做法:迭代器的快速失败行为应该仅用于检测程序错误。
从Java 2 平台 v1.2起,此类就被改进以实现 Map 接口,使它成为 Java
Collections Framework 中的一个成员。不像新的 collection 实现,Hashtable是同步的

2、源码学习

Hashtable只使用了数组和链表来实现结构,比HashMap更简单,内部实现方式和HashMap基本一样

Hashtable计算hash值的方式和HashMap不太相同
hash = key.hashCode();
index = (hash &
0x7FFFFFFF) % tab.length;

Hashtable的线程安全特性主要是通过synchronized 关键字保证的,例如:
public synchronized
V
put(K
key,
V
value) {
// Make sure
the value is not null
if
(value ==
null) {
throw new
NullPointerException();
}

// Makes sure
the key is not already in the hashtable.
Entry<?,?>
tab[] = table;
int
hash = key.hashCode();
int
index = (hash &
0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V>
entry = (Entry<K,V>)tab[index];
for(;
entry !=
null ;
entry = entry.next)
{
if
((entry.hash
== hash) && entry.key.equals(key))
{
V
old = entry.value;
entry.value
= value;
return
old;
}
}

addEntry(hash,
key,
value,
index);
return null;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: