您的位置:首页 > 其它

hashtable源码分析

2015-03-09 20:56 267 查看
虽然hashtable已经不经常用了,但是面试时候还会有很多人问道他与HashMap之间的区别,下来简单看下他和HashMap有什么区别吧~~

首先定义:

public class Hashtable<K,V>  extends Dictionary<K,V>  implements Map<K,V>, Cloneable, java.io.Serializable 在定义部分可以看见,<span style="color:#ff0000;">HashMap集成的AbstractMap,而HashTable继承的Dictionary的类</span>

常量定义:

<span style="white-space:pre">		</span>private transient Entry<K,V>[] table;
private transient int count;
private int threshold;
private float loadFactor;
private transient int modCount = 0;
private static final long serialVersionUID = 1421746759512286392L;
//默认的阈值
static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;


在常量的定义方面,基本和HashMap大同小异

构造方法:4个

和HashMap的类型基本一样。除了名字不一样~~~除了无参的构造默认大小为11,hashmap为16.

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 = new Entry[initialCapacity];
threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
initHashSeedAsNeeded(initialCapacity);
}


常见方法:常见的方法里面,hashtable所有的普通方法都加了synchronized关键字,说明它是线程安全的,而hashmap是现成不安全的。

看看put方法:
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 = 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)) {
V old = e.value;
e.value = value;
return old;
}
}

modCount++;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();

tab = table;
hash = hash(key);
index = (hash & 0x7FFFFFFF) % tab.length;
}

// Creates the new entry.
Entry<K,V> e = tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
return null;
}
这里和HashMap明显有区别的地方在与如何放入hashtable中的元素value为null,则会抛出异常,而hashmap则不会
在这里,如果count的数量大于阈值,会先rehash(),看下rehash函数:
protected void rehash() {
int oldCapacity = table.length;
Entry<K,V>[] oldMap = table;

// overflow-conscious code
int newCapacity = (oldCapacity << 1) + 1;
if (newCapacity - MAX_ARRAY_SIZE > 0) {
if (oldCapacity == MAX_ARRAY_SIZE)
// Keep running with MAX_ARRAY_SIZE buckets
return;
newCapacity = MAX_ARRAY_SIZE;
}
Entry<K,V>[] newMap = new Entry[newCapacity];

modCount++;
threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
boolean rehash = initHashSeedAsNeeded(newCapacity);

table = newMap;

for (int i = oldCapacity ; i-- > 0 ;) {
for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
Entry<K,V> e = old;
old = old.next;

if (rehash) {
e.hash = hash(e.key);
}
int index = (e.hash & 0x7FFFFFFF) % newCapacity;
e.next = newMap[index];
newMap[index] = e;
}
}
}


在rehash扩展table的算法中可以看见,每次扩充为 以前的2倍+1,而hashmap中为2倍;并且hashmap要求table的长度为2的幂,而hashtable中却不需要。

hashtable中的hash算法:

private int hash(Object k) {
// hashSeed will be zero if alternative hashing is disabled.
return hashSeed ^ k.hashCode();
}


这与hashmap中的hash算法也不一样~~~

并且:下面两种方法返回值Enumeration的方法,是hashmap中没有的。

public synchronized Enumeration<K> keys() {
return this.<K>getEnumeration(KEYS);
}


public synchronized Enumeration<V> elements() {
return this.<V>getEnumeration(VALUES);
}

此外,在遍历数据的时候,hashmap采用iterator,hashtable采用了iterator和Enumeration;

具体如下表:

HashMapHashtable
出现时间JDK1.2,所以代码质量更高,更容易明白JDK1.0
并发控制没有考虑并发所有方法都加了synchronized,即使有些我认为不需要的也加了
是否接受值为null的Key 或Value接受不接收。put等方法里面:if (value == null) {

显示throw new NullPointerException();

};int hash=key.hashcode隐示throw NullPointerException();
初始化table缺省容量16。初始化时可以指定initial capacity,若不是2的次方,HashMap将选取第一个大于initial capacity 的2的次方值作为其初始长度缺省容量11。初始化时可以指定initial capacity
扩容添加Entry后判断是否该扩容。扩容至2*oldCapacity先判断是否扩容再添加Entry。扩容至2*oldCapacity + 1
数据遍历的方式IteratorIterator 和 Enumeration
是否支持fast-fail支持fast-fail用Iterator遍历,支持fast-fail
用Enumeration不支持fast-fail.
hash算法和index算法优于Hashtable,通过对Key的hash做移位运算和位的与运算,使其能更广泛地分散到数组的不同位置当数组长度较小,并且Key的hash值低位数值分散不均匀时,不同的hash值计算得到相同下标值的几率较高
实现和继承extends AbstractMap 骨架结构的体现,代码质量上去了extends Dictionary implements Map 直接实现Map接口。多基础了一个已过时的经Dictionary类,就不用去管了
其他代码可以自己参考源码~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: