您的位置:首页 > 其它

史上最详细的Hashtable详解--源码分析

2016-03-29 10:36 393 查看
ps.本文所有源码都是基于jdk1.6

Hashtable数据结构

Hashtable和HashMap的数据结构是一样的,都是一个数组和链表的结合体,如图1-1所示。

private transient Entry[] table;
private transient int count;
private static class Entry<K,V> implements Map.Entry<K,V> {
int hash;
K key;
V value;
Entry<K,V> next;
...
}



图1-1

Hashtable和HashMap的区别

因为Hashtable和HashMap太相似了,所以就不单独介绍Hashtable了,感兴趣的可以先去前面的文章看一下HashMap,再回过头来看这个。

1.继承不同

/** HashMap */
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

/** Hashtable */
public class Hashtable<K,V> extends Dictionary<K,V>implements Map<K,V>, Cloneable, java.io.Serializable


HashMap继承AbstractMap而Hashtable继承Dictionary,现在Dictionary已经被Map取代了,所以有人说继承不同完全是因为历史原因

2.初始容量不同

/** HashMap */
static final int DEFAULT_INITIAL_CAPACITY = 16;
static final float DEFAULT_LOAD_FACTOR = 0.75f;

/** Hashtable */
public Hashtable() {
this(11, 0.75f);
}


//HashMap

HashMap的容量必须是2的幂次方,这个也是有原因的,因为HashMap取table下标的时候,是用h & (length -1 ) 实现的,来保证结果小于等于length -1 ,这个详细介绍在HashMap文章有介绍。为什么HashMap用这种方式实现呢,因为位屏蔽要比整数除法快。

//Hashtable

Hashtable 的容量增加逻辑是乘2+1,保证奇数。

在应用数据分布在等差数据集合(如偶数)上时,如果公差与桶容量有公约数n,则至少有(n-1)/n数量的桶是利用不到的。

实际上 HashMap 也会有此问题,并且不能指定桶容量。所以 HashMap 会在取模哈希前先做一次哈希

3.HashMap接受key和value为null的情况,Hashtable不接受

4.HashMap是线程不同步的,Hashtable是线程同步的

5.扩容策略不同,HashMap扩容2倍,Hashtable扩容2倍+1(为了保证奇数)

/** HashMap */
resize(2 * table.length);

/** Hashtable */
protected void rehash() {
...
int newCapacity = oldCapacity * 2 + 1;
Entry[] newMap = new Entry[newCapacity];
...
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: