HashTable源码分析及底层原理

HashTabled概述

  • Hashtable是个古老的Map实现类,JDK1.0就提供了。不同于HashMap,Hashtable是线程安全的。
  • Hashtable实现原理和HashMap相同,功能相同。底层都使用数组+链表结构,查询速度快,很多情况下可以互用。
  • 与HashMap不同,Hashtable不允许使用null作为key和 value
  • 与HashMap一样,Hashtable 也不能保证其中 Key-Value对的顺序Hashtable判断两个key相等、两个value相等的标准,与HashMap一致。

源码分析

成员变量

(1)table是一个Entry[]数组类型,而Entry实际上就是一个单向链表。哈希表的"key-value键值对"都是存储在Entry数组中的。
(2)count是Hashtable的大小,它是Hashtable保存的键值对的数量。
(3)threshold是Hashtable的阈值,用于判断是否需要调整Hashtable的容量。threshold的值=“容量*加载因子”。
(4)loadFactor就是加载因子。
(5)modCount是用来实现fail-fast机制的

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


    /**
     * The hash table data.
     */
    private transient Entry<?,?>[] table;


    /**
     * The total number of entries in the hash table.
     */
    private transient int count;


    /**
     * The table is rehashed when its size exceeds this threshold.  (The
     * value of this field is (int)(capacity * loadFactor).)
     */
    private int threshold;


    /**
     * The load factor for the hashtable.
     */
    private float loadFactor;


    private transient int modCount = 0;

构造函数

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);
}

public Hashtable(int initialCapacity) {
    this(initialCapacity, 0.75f);
}

/**
* Constructs a new, empty hashtable with a default initial capacity (11)
* and load factor (0.75).
*/
public Hashtable() {
    this(11, 0.75f);
}

get方法

最大的不同在于保证同步

@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;
}

put方法

public synchronized V put(K key, V value) {  
        // 确保value不为null  
        if (value == null) {  
            throw new NullPointerException();  
        }  
  
        /*
         * 确保key在table[]是不重复的
         * 处理过程:
         * 1、计算key的hash值,确认在table[]中的索引位置
         * 2、迭代index索引位置,如果该位置处的链表中存在一个一样的key,则替换其value,返回旧值
         */  
        Entry tab[] = table;  
        int hash = hash(key);    //计算key的hash值  
        int index = (hash & 0x7FFFFFFF) % tab.length;     //确认该key的索引位置  
        //迭代,寻找该key,替换  
        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();  
            tab = table;  
            hash = hash(key);  
            index = (hash & 0x7FFFFFFF) % tab.length;  
        }  
  
        // 在索引位置处插入一个新的节点  
        Entry<K,V> e = tab[index];  
        tab[index] = new Entry<>(hash, key, value, e);  
        //容器中元素+1  
        count++;  
        return null;  
    }  

总结

HashTable存储结构与JDK 7以前的HashMap类似,即数组加上链表结构,用链表法解决哈希碰撞

最大的不同在于用synchronized保证了线程同步

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值