JAVA之HashMap实现原理分析-1

本文深入探讨了HashMap的工作原理,包括其内部结构、put和get操作流程,以及如何利用hashCode提高查找效率。

1、HashMap一般使用场景:

HashMap为key-value对存储方式,允许key或者value的值为null,这也是与HashTable的区别之一,在本人所做的项目中,一般使用HashMap来做系统内部数据缓存,例如:需要通过一个设备的唯一标识来快速找到到设备的实体对象,或者需要快速定位到某一对象进行操作,如果您也有这样的需求,在合适的场景下可以考虑使用HashMap来处理。当然这不只是HashMap的唯一用处。

2、HashMap使用疑问:

HashMap是如何快速根据key值定位到value值的?在使用HashMap的时候,如果多次调用put方法的key值重复,HashMap的底层又是如何处理的?下面逐一分析。

3、HashMap结构:

根据源码分析,HashMap内部其实是由Entry[] table构成,在新建一个HashMap的时候JDK代码如下:

    transient Entry[] table;
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
        init();
    }

由此可见,HashMap的内部其实维持了一个Entry数组,那咱们就来看看Entry的结构:

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

        /**
         * Creates new entry.
         */
        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
	}
}

从上述代码可以看出,Entry有一个next属性指向下一个Entry实体,咱们可以将其理解为链表结构。整个HashMap类似如此结构:

众说周知,java的每一个对象均有一个hashCode方法,调用该方法可以活得对象的散列值,HashMap内部通过以下代码获取需要存储的对象应该存储在Entry[] table的哪个位置:

  int hash = hash(key.hashCode());

4、HashMap的put操作:

 整个put操作基本可以分为三个步骤:

获取存储数组索引位置。

遍历特定位置上的Entry链表,是否已经存在key值一样的数据,有则覆盖value值,完成put操作。

向特定位置上的Entry链表添加新put数据,注意,在链表表头添加。具体实现代码如下:

 int hash = hash(key.hashCode());
 int i = indexFor(hash, table.length);

------------------以上为第一步骤执行代码------------------------------------

    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

----------------以上为第二步骤代码,根据以上代码也就解释了为什么put的时候key一样,value值会被最新的值覆盖掉。通过equals方法判断两个key值是否相等,如果执行了覆盖,则不执行第三步操作。-------------------------

    void addEntry(int hash, K key, V value, int bucketIndex) {
	Entry<K,V> e = table[bucketIndex];
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
        if (size++ >= threshold)
            resize(2 * table.length);
    }

--------------以上为第三步骤代码,可以看出,新增了一个Entry实体,并将其next属性指向了操作之前的链表头元素,相当于将新的Entry实体加入到了链表头部--------------

5、HashMap的get操作-- (xhEditor不知道怎么回事,不能选中文字改变字体颜色了。。。):

    public V get(Object key) {
        if (key == null)
            return getForNullKey();
        int hash = hash(key.hashCode());
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

从上面的代码可以看出,与put方法的第一二步类似,首先找到Entry数组索引,再根据key值来获取value值,也是通过key的equals来判断。

6、总结:

HashMap为何可以快速根据key定位到value值,其实就是通过key的hashCode方法快速找到了value值所在的Entry链表,只需要在定位后的Entry链表中寻找value值就可以了,不需要全局全量定位,大大提高了操作效率。

其实个人认为可能HashMap是这种结构有如下原因:

数组本来就是寻址容易,操作困难,包括插入和删除。

链表本来就是寻址困难,操作容易。

HashMap就是用数组来寻找再用链表来进行操作,使二者优势结合。

内容概要:本文系统梳理了多个科研领域的前沿研究与技术实现,重点涵盖FDTD方法中的完美匹配层(PML)研究,以及Matlab/Simulink在电磁、电力、控制、通信、信号处理、图像处理、路径规划、能源系统优化等领域的仿真与算法实现。文中列举了大量基于Matlab和Python的科研案例,如风电功率预测、负荷预测、无人机三维路径规划、电池系统故障诊断、雷达模拟、通信编码、微电网优化调度等,并强调结合智能优化算法(如粒子群、遗传算法、深度学习等)提升系统性能。同时,提供了丰富的代码资源与仿真模型,涵盖永磁同步电机控制、逆变器设计、多智能体任务分配、虚拟电厂调度等复杂系统,助力科研人员快速开展复现实验与创新研究。; 适合人群:具备一定编程基础,熟悉Matlab/Python工具,从事电气工程、自动化、通信、人工智能、新能源、控制科学等相关领域研究的研发人员及研究生。; 使用场景及目标:① 学习并实现FDTD仿真中的PML边界条件以有效抑制数值反射;② 掌握Matlab/Simulink在多物理场建模、控制系统设计与优化算法中的综合应用;③ 借助提供的代码资源完成科研复现、课程设计、竞赛项目或工程原型开发; 阅读建议:此资源以科研实战为导向,不仅提供理论方法,更强调代码实现与仿真验证。建议读者结合自身研究方向,按目录顺序查阅相关模块,下载配套代码进行调试与二次开发,以达到学以致用、融会贯通的目的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值