Java学习之-HashMap分析

文章详细分析了Java中HashMap的put方法,包括其内部的哈希计算、节点插入过程,以及在遇到键值冲突时如何处理,特别是当链表长度达到一定阈值时转换为红黑树的机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HashMap分析

HashMap底层结构是 数组+链表+红黑树,线程不是安全的,key-value都允许为空
性能高,元素顺序结构是无序的并且key不允许重复。
HashMap:适用于Map中插入、删除和定位元素。

put方法详解

package com.studycollectionormap;


import java.util.HashMap;

/**
 * put方法详解
 * @author admin
 * @version 1.0
 * HashMap
 */
@SuppressWarnings({"all"})
public class HashMapOrConcurrentHashMap {
    public static void main(String[] args){
        /**
         *    1. 创建HashMap对象
         *    创建无参构造器  初始化加载因子loadFactor 为 0.75
         *     public HashMap() {
         *         this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
         *     }
         */
        HashMap map = new HashMap();
        map.put("aa", 12);
        map.put("bb", "dd");
        map.put("aa", "cc");
        System.out.println("map" + map);
        /**
         *     put方法解读(个人理解)
         *    2. public V put(K key, V value) {
         *          传入key   和   value,计算hash值 (return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);)
         *          然后调用putVal方法
         *         return putVal(hash(key), key, value, false, true);
         *     }
         *
         *    3.执行put方法
         *     putVal方法解读(个人理解)
         *     传入hashi值,key,value
         *     final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
         *                    boolean evict) {
         *          //创建辅助变量
         *         Node<K,V>[] tab; Node<K,V> p; int n, i;
         *         if ((tab = table) == null || (n = tab.length) == 0)
         *         //如果底层table为空 或者 length 为0 ,则扩容 16(相当于第一次添加数据)
         *             n = (tab = resize()).length;
         *         //根据hash值计算出table索引位置的Node节点,如果为空,就直接把加入的  k-v,创建成一个Node,加入该位置
         *         //理解为算出索引位置 如果没有就直接加入
         *         if ((p = tab[i = (n - 1) & hash]) == null)
         *             tab[i] = newNode(hash, key, value, null);
         *         else {
         *             //第二次添加走这里
         *             Node<K,V> e; K k;//创建辅助变量
         *             //p.hash为已有数据的hash值,p.key为已有数据的key
         *             //如果已有数据的key的hash值与新传入key的hash值相同
         *             //且满足已有数据的key与新加入的key是同一个对象,并且他们的 equals返回为真
         *             //则表示不能添加新的key
         *             if (p.hash == hash &&
         *                 ((k = p.key) == key || (key != null && key.equals(k))))
         *                 e = p;
         *              //如果当前table中已有node是一个红黑树就按照红黑树规则添加
         *             else if (p instanceof TreeNode)
         *                 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
         *             else {
         *                  //这个else里面写的是 你已经算出了你要存放在某个位置了,但是这个位置是一个链表结构
         *                  //就会对已有链表的每个元素进行一个循环对比
         *                 for (int binCount = 0; ; ++binCount) { //死循环
         *                      //如果已有数据的next为空,则创建 Node节点放入这个位置(理解:为最后一个)
         *                     if ((e = p.next) == null) {
         *                         p.next = newNode(hash, key, value, null);
         * 						   //如果这个p.next刚好为8的最后一个则满足下面条件调用treeifyBin方法
         *                         //如果链表个数是否大于等于8
         *                         //如果满足上面条件则调用 treeifyBin(tab, hash);方法 
         *                         if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
         *                             treeifyBin(tab, hash);
         *                         break;
         *                     }
         *                     //如果p.next 不为空,则判断key和hash值是否相同,如有相同直接break 放弃添加
         *                     if (e.hash == hash &&
         *                         ((k = e.key) == key || (key != null && key.equals(k))))
         *                         break;
         *                     p = e;
         *                 }
         *             }
         *             //e不等于空,说明找到了相同的key,相同key进行 value值替换
         *             if (e != null) { // existing mapping for key
         *                 V oldValue = e.value;
         *                 if (!onlyIfAbsent || oldValue == null)
         *                     //value值替换
         *                     e.value = value;
         *                 afterNodeAccess(e);
         *                 return oldValue;
         *             }
         *         }
         *         //操作次数加一
         *         ++modCount;
         *         //每新增一个node,就size++
         *         if (++size > threshold)
         *         //如果长度大于临界值 (0.75*16) 则扩容
         *             resize();
         *         afterNodeInsertion(evict);
         *         //输出为空表示成功
         *         return null;
         *     }
         *
         *     //何时转为红黑树(如果链表长度大于8个并且table的大小大于64就会进行树化)
         *     //如果table为空或者长度小于MIN_TREEIFY_CAPACITY(64),暂时不会树化而是扩容
         *     final void treeifyBin(Node<K,V>[] tab, int hash) {
         *         int n, index; Node<K,V> e;
         *         if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
         *             resize();
         *     }
         *
         */
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值