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

Java 学习系列: Hashtable的实现原理

2016-04-01 14:49 459 查看
1 . Hashtable概述:

Hashtable继承了Dictionary(已经不提倡继承此类了),然后实现了Map接口,可以执行Map所含的所有方法,并且允许Null key和Null值;

Hashtable有两个重要的初始化参数会影响到它的表现,分别是initial capacity(buckets的容量)和load factor(扩增因子);当buckets(容器)内部元素个数接近达到load factor*current capacity大小时,这个Hash 表就会重新构建分布(内部数据结构会重构),新的buckets大概会扩增到之前大小的两倍左右;通常默认的load factor是 (.75),这时会使时间与空间消耗的效率达到最优。比这个值高可以节约一点空间消耗,但会增加Map相关所有操作的查找时间(包括put,get,等)。当设置Hash表的初始大小时,应该把所预计的实体大小和load factor的大小一起计算到其中,以减少rehash的次数;如果Hash表的初始大小大于由load factor分散的预计实体集合的大小,那就永远不会发生rehash操作;

当我们要用一个Hash表存放大量的映射对象时,可以创建一个初始化大小很大的对象,那样会提高put的效率;

对于Hashtable的iterators,如果再创建迭代器后,再对连表结构进行改变操作,那再调用迭代器的方法时,除了会抛出迭代器本身的异常外,还一定会抛出ConcurrentModificationException异常,因此在多线程环境环境,迭代器会快速失败和清除,以防止在未来产生不确定的问题,行为等。

注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。

Hashtable的get,put,contains等方法都加了锁,实现了同步

2 . 相关代码

1). get 方法

/**
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*
* <p>More formally, if this map contains a mapping from a key
* {@code k} to a value {@code v} such that {@code (key.equals(k))},
* then this method returns {@code v}; otherwise it returns
* {@code null}.  (There can be at most one such mapping.)
*
* @param key the key whose associated value is to be returned
* @return the value to which the specified key is mapped, or
*         {@code null} if this map contains no mapping for the key
* @throws NullPointerException if the specified key is null
* @see     #put(Object, Object)
*/
@SuppressWarnings("unchecked")
public synchronized V get(Object key) {
Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
return (V)e.value;
}
}
return null;
}


2). put 方法

/**
* Maps the specified <code>key</code> to the specified
* <code>value</code> in this hashtable. Neither the key nor the
* value can be <code>null</code>. <p>
*
* The value can be retrieved by calling the <code>get</code> method
* with a key that is equal to the original key.
*
* @param      key     the hashtable key
* @param      value   the value
* @return     the previous value of the specified key in this hashtable,
*             or <code>null</code> if it did not have one
* @exception  NullPointerException  if the key or value is
*               <code>null</code>
* @see     Object#equals(Object)
* @see     #get(Object)
*/
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;
}


3). contains 方法

/**
* Tests if some key maps into the specified value in this hashtable.
* This operation is more expensive than the {@link #containsKey
* containsKey} method.
*
* <p>Note that this method is identical in functionality to
* {@link #containsValue containsValue}, (which is part of the
* {@link Map} interface in the collections framework).
*
* @param      value   a value to search for
* @return     <code>true</code> if and only if some key maps to the
*             <code>value</code> argument in this hashtable as
*             determined by the <tt>equals</tt> method;
*             <code>false</code> otherwise.
* @exception  NullPointerException  if the value is <code>null</code>
*/
public synchronized boolean contains(Object value) {
if (value == null) {
throw new NullPointerException();
}

Entry<?,?> tab[] = table;
for (int i = tab.length ; i-- > 0 ;) {
for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
if (e.value.equals(value)) {
return true;
}
}
}
return false;
}


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