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

Java提高(二)---- HashTable

2017-05-04 14:41 239 查看

阅读博客

java提高篇(二五)—–HashTable

这篇博客由chenssy 发表与2014年4月,基于源码是jdk1.7

 

==========================

本文针对jdk1.8的HashTable源码补充说明

 

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;
// 直接使用key的hashCode作为hash值。 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; }

 

HashTable的key和value都不能为null

HashTable不会对key的hashCode进行再哈希,直接使用。

在取table的索引时,先取hash的低31位,然后对table的长度取模。这样速度比HashMap要慢。HashMap已经考虑到这个问题,所以HashMap的table长度

是2的n次方,直接按位计算,就能得到索引,而不需要%计算了。

put使用了synchronize修饰,多线程安全。

 

在每次添加元素时,会判断当前元素数量是否超过了阈值,超过了,就要rehash,进行扩容。

jdk1.8 rehash源码

protected void rehash() {
int oldCapacity = table.length;
Entry<?,?>[] 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<?,?>[] newMap = new Entry<?,?>[newCapacity];

modCount++;
threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
table = newMap;

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

int index = (e.hash & 0x7FFFFFFF) % newCapacity;
e.next = (Entry<K,V>)newMap[index];
newMap[index] = e;
}
}
}

在chenssy的博客中,下面这行有笔误,少了数组的长度。

Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];

 

 

jdk1.8 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是同步的,用synchronize修饰了get方法和put方法。而HashMap 没有这个修饰,

2,HashTable不允许key和value为null,HashMap允许。

3,HashTable使用的是Enumerator迭代器,不是fail-fast的, HashMap的迭代器更多,而且是fail-fast的。

4,他们的hash函数不同。但这个问题吧,其实就算是HashMap在不同的jdk版本中,hash函数也不同。HashTable不会对key的hashCode进行再哈希。HashMap会对key的hashCode再hash。

5,table的容量不容,HashMap的table容量总是2的n次方,这样方便了计算index值,提高了效率。HashTable的table容量比较随意,默认值是11,所以计算index时要费劲些。

HashMap在性能上要好于HashTable.

6,HashTable继承自Dictionary,实现了Map接口, HashMap继承自AbstractMap,实现了Map接口。

 

HashTable比较老,jdk1.0就有了

HashMap和 TreeMap jdk1.2才有

ConcurrentHashMap jdk1.5才有。

 

区别方面参考博客

http://www.importnew.com/7010.html (HashMap和Hashtable的区别) 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: