Map的实现类Hashtable各种方法源码解析

  1. map.put 方法解析

    // map.put 方法 不能存null的key和value 
    // 不成立:map.put(null, null) map.put(null,Object) map.put(Object, null) 
    // map.put 在这里没有如果put不满足的数值 会抛出异常 java.lang.NullPointerException
    public synchronized V put(K key, V value) {
            // Make sure the value is not null
            if (value == null) {// key也不能为null 可以为字符串: "",字符串""的 hash 为0
                throw new NullPointerException();
            }
    
            // Makes sure the key is not already in the hashtable.
            Entry<?,?> tab[] = table;//定义tab[]
            int hash = key.hashCode();//取key的hash值
            int index = (hash & 0x7FFFFFFF) % tab.length;//取模运算 计算需要存储的位置
            @SuppressWarnings("unchecked")
            Entry<K,V> entry = (Entry<K,V>)tab[index];
            //确定当前位置是否已存在数据,hash存储会有数据碰撞的几率,这就是为什么说两个对象的        
            // hashcode相等,值却不一定相等的原因,例如: Aa 和 BB 的hashCode 都是2112 
            //循环判断当前需要存储的位置的entry是否为已存储的数据,hash表存储数据格式(数组与链表存储    
            //的结合) 成立则覆盖oldValue并返回old 不成立则继续循环下一个
            for(; entry != null ; entry = entry.next) {
                // 判断是否是重复key数据put
                if ((entry.hash == hash) && entry.key.equals(key)) {
                    V old = entry.value;
                    entry.value = value;
                    return old;
                }
            }
    
            addEntry(hash, key, value, index);//执行newEntry的add操作
            return null;
        }
        
        // addEntry方法解析 执行数组的扩容操作以及add操作
        private void addEntry(int hash, K key, V value, int index) {
            modCount++;
    
            Entry<?,?> tab[] = table;//定义tab[]
            //判断当前的存储数量是否超出或等于当前数组最大的容量阀值
            if (count >= threshold) {
                // Rehash the table if the threshold is exceeded
                rehash();//执行扩容的方法 oldCP * 2 + 1
    
                tab = table;//扩容之后的newTable
                hash = key.hashCode();
                index = (hash & 0x7FFFFFFF) % tab.length;//取模计算需要存放的位置
            }
    
            // Creates the new entry.
            @SuppressWarnings("unchecked")
            Entry<K,V> e = (Entry<K,V>) tab[index];// 取当前位置是否存在oldEntry
            //执行Entry的链表存储结构先入的放到后面
            //protected Entry(int hash, K key, V value, Entry<K,V> next) {
                //this.hash = hash;
                //this.key =  key;
                //this.value = value;
                //this.next = next;
            //}
            tab[index] = new Entry<>(hash, key, value, e);
            count++;
        }
        
        // rehash() 方法 执行数组的扩容方法 oldCp * 2 + 1
        @SuppressWarnings("unchecked")
        protected void rehash() {
            int oldCapacity = table.length;//定义oldCp
            Entry<?,?>[] oldMap = table;// 定义 oldMap 执行copy时使用 执行扩容之后的数组为table
    
            // overflow-conscious code
            int newCapacity = (oldCapacity << 1) + 1;// newCp 为 oldCp * 2 + 1
            if (newCapacity - MAX_ARRAY_SIZE > 0) {// HashTable 的最大容量是MAX_ARRAY_SIZE
                if (oldCapacity == MAX_ARRAY_SIZE)
                    // Keep running with MAX_ARRAY_SIZE buckets
                    return;
                newCapacity = MAX_ARRAY_SIZE;// 定义newCp 为MAX_ARRAY_SIZE
            }
            Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
    
            modCount++;
            // 最大容量阀值为 newCp * 0.75(默认) 或者 MAX_ARRAY_SIZE + 1 
            threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
            table = newMap;// 从新定义table 执行copy操作
    
            for (int i = oldCapacity ; i-- > 0 ;) {// 循环执行数据的copy
                // 执行 散列表数据结构的 copy 
                for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
                    Entry<K,V> e = old;// 将oldEntry 赋值 给e
                    old = old.next;// 从新定义oldEntry 为old.next
                    
                    int index = (e.hash & 0x7FFFFFFF) % newCapacity;// 取模计算新数组的存放位置
                    e.next = (Entry<K,V>)newMap[index];//防止数据丢失 链表存储结构 先入后出 
                    newMap[index] = e;// 执行数据的存放
                }
            }
        }

     

  2. map.get(key) 方法解析

        // map.get() 方法源码解析
        @SuppressWarnings("unchecked")
        public synchronized V get(Object key) {
            Entry<?,?> tab[] = table;// 定义tab[]
            int hash = key.hashCode();//取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;//成功返回value
                }
            }
            return null;//无匹配数据返回null
        }

     

  3. map.putAll(Map<? extends K, ? extends V> m)  方法解析

        // map.putAll() 方法源码解析
        // 循环执行map数据的put操作 
        public synchronized void putAll(Map<? extends K, ? extends V> t) {
            for (Map.Entry<? extends K, ? extends V> e : t.entrySet())
                put(e.getKey(), e.getValue());// put源码
        }

     

  4. map.remove(key) 方法解析

        // map.remove(Object key) 方法源码解析
        // remove 的方法 是先执行get(key) 方法 在执行数据的remove
        public synchronized V remove(Object key) {
            Entry<?,?> tab[] = table;//定义tab[]
            int hash = key.hashCode();//去key的hashCode
            int index = (hash & 0x7FFFFFFF) % tab.length;//与运算 取模 计算数据的存储位置
            @SuppressWarnings("unchecked")
            Entry<K,V> e = (Entry<K,V>)tab[index];// 找到需要remove的链表数据结构对象
            //循环对比 找到需要remove的对象
            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 != null 链表数据结构remove 只需要移动指针操作
                        prev.next = e.next;
                    } else {
                        tab[index] = e.next;//当前链表的first位置,移动指针操作
                    }
                    count--;
                    V oldValue = e.value;
                    e.value = null;// 设置为null 方便回收
                    return oldValue;//返回remove的value值
                }
            }
            return null;// 不匹配返回null
        }

     

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值