分析源码理解HashMap——为速度而散列

HashMap是Java中的一种高效数据结构,基于数组和链表/红黑树实现。其通过散列码快速定位元素,利用hashCode()和equals()处理冲突。JDK8中,当链表长度达到8时,会转换为红黑树以提高执行效率。初始容量和加载因子影响HashMap的性能,当使用率达到加载因子时,会进行扩容。
摘要由CSDN通过智能技术生成

概述

HashMap实现了Map接口,也是以键值对(K-V)的形式的一种数据结构,其内部由数组+链表/红黑树实现。

特点

以键值对(K-V)存储

不保证顺序

查询速度快

允许使用 null 做键和值

非线程安全

为什么速度快

HashMap查询速度很快,是因为它由散列的方法来计算元素的存储位置和元素的查找。上面提到,HashMap是数组+链表/红黑树实现的。简单来说就是,创建HashMap对象时,内部会初始化一个数组,添加元素时根据元素的Key,通过特殊算法计算出一个 int 类型的散列码,这个散列码其实就是该元素要存储在数组上的位置(数组下标)。

数组:是用来存储键的信息(注意,是键的信息,不是存键本身),为什么不直接存键本身呢?因为数组不能调整容量,但又希望Map中保持数量不确定的的值,让不同的键可以产生相同的下标(也就是说,可能会有冲突)。多个键产生同个下标后,会以链表的形式存储:

查询一个值得过程,首先要根据 Key 计算出散列码,然后根据散列码查询数组,如果这个时候没有冲突,那是最完美的,不用再进一步查询链表,如果有冲突,那就要使用 equals() 方法进行线性查询,可以看出,冲突越多,查找性能会越差。所以 Jdk8 中做了优化,当链表长度超过 8 的时候,用红黑树的结构存储(红黑树这里不做细说)。

这种查询值得方式不需要线性的遍历所有元素,而是通过散列码快速定位到数组的某个位置,只对很少的元素进行比较,这就是HashMap如此快的原因。

jdk8 put、get、remove源码解析(jdk8)

put

    public V put(K key, V value) {
        // 对key计算 hash值(散列码),然后传递给 putVal 方法
        return putVal(hash(key), key, value, false, true);
    }

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;// p 可以理解为数组该位置链表的第一个元素
        // 判断数组是否为空,如果为空。
        if ((tab = table) == null || (n = tab.length) == 0)
            // 调用 resize() 初始化创建
            n = (tab = resize()).length;
        // 散列码取模得到数组下标 i,并判断该位置是否为 null
        if ((p = tab[i = (n - 1) & hash]) == null)
            // 说明还没有元素被散列到此(该位置没冲突&#x
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值