Java集合-Hashtable源码解析-JDK1.8

Hashtable简介

推荐查看此篇文章之前首先查看 HashMap源码分析 效果更佳哦

与HashMap的数组加链表加红黑树不同,Hashtable在jdk 1.8中仅仅使用了数组+链表的方式进行存储。

HashMap的属性

HashMap的一些基础属性:

/**	
     * 保村数据的数组	
     */	
    private transient Entry<?, ?>[] table;	

	
    /**	
     * 数组的元素数量	
     */	
    private transient int count;	

	
    /**	
     * 扩容阈值	
     *	
     * @serial	
     */	
    private int threshold;	

	
    /**	
     * 加载因子	
     */	
    private float loadFactor;	

	
    /**	
     * 被修改的次数	
     */	
    private transient int modCount = 0;	

	
    /**	
     * use serialVersionUID from JDK 1.0.2 for interoperability	
     */	
    private static final long serialVersionUID = 1421746759512286392L;	
    /**	
     *最大容量	
     */	
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;	

HashMap存储数据所使用的链表数据结构:

private static class Entry<K, V> implements Map.Entry<K, V> {	
        final int hash;	
        final K key;	
        V value;	
        Hashtable.Entry<K, V> next;	

	
        protected Entry(int hash, K key, V value, Hashtable.Entry<K, V> next) {	
            this.hash = hash;	
            this.key = key;	
            this.value = value;	
            this.next = next;	
        }	
    }

Hashtable的构造方法

 /**	
     * 指定初始容量和加载因子	
     */	
    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);	
    }	

	
    /**	
     * 指定初始容量,加载因子使用默认的0.75	
     */	
    public Hashtable(int initialCapacity) {	
        this(initialCapacity, 0.75f);	
    }	

	
    /**	
     * 默认构造方法	
     */	
    public Hashtable() {	
        this(11, 0.75f);	
    }	

	
    /**	
     * 添加一个map	
     */	
    public Hashtable(Map<? extends K, ? extends V> t) {	
        this(Math.max(2 * t.size(), 11), 0.75f);	
        putAll(t);	
    }

Hashtable的添加方法

/**	
     * 添加方法	
     */	
    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的哈希值	
        int hash = key.hashCode();	
        //计算key应该放的索引	
        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;	
    }	
     private void addEntry(int hash, K key, V value, int index) {	
        //修改次数增加	
        modCount++;	

	
        Entry<?, ?> tab[] = table;	
        //判断是否需要扩容	
        if (count >= threshold) {	
            // Rehash the table if the threshold is exceeded	
            rehash();	

	
            tab = table;	
            //对本次添加的元素重新计算hash	
            hash = key.hashCode();	
            index = (hash & 0x7FFFFFFF) % tab.length;	
        }	

	
// Creates the new entry.	
        @SuppressWarnings("unchecked")	
        Entry<K, V> e = (Entry<K, V>) tab[index];	
        tab[index] = new Entry<>(hash, key, value, e);	
        count++;	
    }

Hashtable的扩容

  /**	
     * 扩容方法	
     */	
    @SuppressWarnings("unchecked")	
    protected void rehash() {	
        int oldCapacity = table.length;	
        Entry<?, ?>[] oldMap = table;	

	
        // 尝试扩容2倍再+1	
        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;	
            }	
        }	
    }

Hashtable的查找

 

  /**	
     * 查找方法	
     */	
    @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;	
    }

查找时先定位键值对所在的桶的位置,然后再对链表或红黑树进行查找

Hashtable的删除

/**	
     * 删除方法	
     */	
    public synchronized V remove(Object key) {	
        Entry<?, ?> tab[] = table;	
        //计算hash	
        int hash = key.hashCode();	
        int index = (hash & 0x7FFFFFFF) % tab.length;	
        @SuppressWarnings("unchecked")	
        Entry<K, V> e = (Entry<K, V>) tab[index];	
        //遍历链表删除	
        for (Entry<K, V> prev = null; e != null; prev = e, e = e.next) {	
            if ((e.hash == hash) && e.key.equals(key)) {	
                modCount++;	
                if (prev != null) {	
                    prev.next = e.next;	
                } else {	
                    tab[index] = e.next;	
                }	
                count--;	
                V oldValue = e.value;	
                e.value = null;	
                return oldValue;	
            }	
        }	
        return null;	
    }

看了Hashtable的增删改查方法你就明白了为什么他是线程安全的了这哥们的方法都是使用synchronize修饰的。

鉴于篇幅有限,本篇文章仅列出上方部分代码,Hashtable完整源码解析请 点击下方“阅读原文”查看!!!

640?wx_fmt=jpeg

万水千山总是情,点个 “在看” 行不行!!!

640?wx_fmt=png 

weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值