HashTable<k,v>源码解析

源码

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

从源码中可知,HashTable 继承与 Dictionary 类,同时实现了 Map 、Cloneable、Serializable接口。Dictionary 类是任何可将键映射到相应值得类 (如 Hashtable)的抽象父类。每个键和值都是对象。

Dictionary源码

public abstract class Dictionary<K,V>
extends Object

成员变量:
Hashtable是通过”拉链法”实现的哈希表。它包括几个重要的成员变量:table, count, threshold, loadFactor, modCount

/**
 * table是一个 Entry[] 数组类型,哈希表的"key-value键值对"都是存储在Entry数组中的
 */
private transient Entry<?,?>[] table;

/**
 * count 是 Hashtable 的大小,它是 Hashtable 保存的键值对的数量
 */
private transient int count;

/**
 * threshold 是 Hashtable 的阈值,用于判断是否需要调整 Hashtable 的容量。threshold 的值="容量*加载因子"
 *
 * @serial
 */
 private int threshold;

/**
 * 加载因子.
 *
 * @serial
 */
private float loadFactor;

/**
 * The number of times this Hashtable has been structurally modified
 * Structural modifications are those that change the number of entries in
 * the Hashtable or otherwise modify its internal structure (e.g.,
 * rehash).  This field is used to make iterators on Collection-views of
 * the Hashtable fail-fast.  (See ConcurrentModificationException).
 */
private transient int modCount = 0;

构造方法

Hashtable()
构造一个空的哈希表,其中有默认初始容量(11)和加载因子(0.75)。.
Hashtable(int initialCapacity)
使用指定的初始容量和默认加载因子(0.75)构造一个新的哈希表。
Hashtable(int initialCapacity, float loadFactor)
使用指定的初始容量和指定的负载因素构造一个新的hashtable。
Hashtable(Map<? extends K,? extends V> t)
使用与给定映射相同的映射构造一个新的哈希表

put 方法
判断 value 是否为空,为空则抛出异常;
计算 key 的 hash 值,并根据 hash 值获得 key 在 table 数组中的位置 index,如果 table[index] 元素不为空,则进行迭代,如果遇到相同的 key,则直接替换,并返回旧 value;
否则,我们可以将其插入到 table[index] 位置。

public V put(K key,V value)
将指定的键映射到这个散列表中指定的值。键值和值都不能为空。通过使用与原始密钥相同的键调用get方法,可以检索该值。

指定:
put in interface Map<K,V>
put in class Dictionary<K,V>
参数:
key - 键
value - 值
返回:
在这个散列表中指定的键的前一个值,如果没有一个键值,则为null
异常:
NullPointerException - 如果键值为null

get 方法
相比较于 put 方法,get 方法则简单很多。其过程就是首先通过 hash()方法求得 key 的哈希值,然后根据 hash 值得到 index 索引(上述两步所用的算法与 put 方法都相同)。然后迭代链表,返回匹配的 key 的对应的 value;找不到则返回 null

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 基于 Dictionary 类,而 HashMap 是基于 AbstractMap。Dictionary 是任何可将键映射到相应值的类的抽象父类,而 AbstractMap 是基于 Map 接口的实现,它以最大限度地减少实现此接口所需的工作。
2、HashMap 的 key 和 value 都允许为 null,而 Hashtable 的 key 和 value 都不允许为 null。HashMap 遇到 key 为 null 的时候,调用 putForNullKey 方法进行处理,而对 value 没有处理;Hashtable遇到 null,直接返回 NullPointerException。
3、Hashtable 方法是同步,而HashMap则不是。我们可以看一下源码,Hashtable 中的几乎所有的 public 的方法都是 synchronized 的,而有些方法也是在内部通过 synchronized 代码块来实现。所以有人一般都建议如果是涉及到多线程同步时采用 HashTable,没有涉及就采用 HashMap,但是在 Collections 类中存在一个静态方法:synchronizedMap(),该方法创建了一个线程安全的 Map 对象,并把它作为一个封装的对象来返回。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@SokachWang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值