3. HashMap源码: hashmap方法(增添节点部分)

本文详细探讨HashMap的tableSizeFor方法,用于获取最小2整数幂的扩容策略。接着分析hash方法,解释如何确保键的有效分布。接着讨论了resize方法,包括扩容条件和操作过程。此外,还介绍了put和putVal方法,插入节点的过程,包括单链表和红黑树的处理。最后,提到了treeifyBin方法,将链表转换为红黑树以优化性能。
摘要由CSDN通过智能技术生成

hashmap方法

tableSizeFor:获取最小2整数幂

作用是查找大于等于传参容量的最小2的整数幂,赋值给threshold阈值。由于扩容是当前数组下标值加上原数组长度,所以需要扩充到原先两倍大小,又因为初始是16,所以一定扩容后的大小是2的整数幂。

static final int tableSizeFor(int cap) {
   
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

作用就是获取一个满足大于等于cap(传入参数,原容量)且是2的整数幂的数之中最小的数。

首先-1是当cap本身就是2的整数幂的时候,满足包含自身,也就是扩容后的结果还是cap。

|= : n=n| (n >>> 1)

|:左右两个元素位运算,都是0时该位才是0

n>>> 1: n的二进制向右移动1位,左边高位空出来的补0

代码目的就是把n的非0最高位的后面全变成1(0000100变成了0000111)

这样在+1就获得了最小的2的整数幂并且大于等于n

hash:判断hash值(只考虑key)

  1. ^是异或方法 : 左右值相同是0,不同是1
  2. 1.8 中用的是key的hashcode,注意这里和高16位做了一个异或,可以防止hash数组太小时,hash值的高位被忽略,也就是太小左
static final int hash(Object key) {
   
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
  1. 桶定位: 用的方法是hash & (table.length -1),也就是hash方法得到的hash值和table数组的长度-1,取并。(相当于h%length)

hashcode, ==, equals, compareTo()区别

可以参考博客:12

== 比较的是变量的句柄存储地址,而不是实际存储内容

equals比较的是实际的存储内容,所以自定义类需要重写equals方法,否则继承Object中的equals方法,还是比较句柄地址和==一样。(因为Object类中的equals只是判断两个引用变量是否引用同一对象,如果不是引用同一对象,即使两个对象的内容完全相同,也会返回false。)

hashcode:hashcode是将物理地址转换成一个int数进行比较,同一地址才相同。

和equals方法没有强制关系,也需要重写。保证结果是hashcode相同equals不一定相同,equals为真两对象相等hashcode一定相等。

compareTo(): 获取的字符串(也可以是其他对象)的长度,然后作减法,这里的减法就是ASCII码的减法,所以compareTo()会返回数字,如果两个字符串内容相同,会返回0,字符串a大于字符串b,会返回相差的ASCII码的正数,字符串a小于字符串b,会返回相差的ASCII码的负数。

简而言之就是从长度不同返回长度差,长度相同返回编码差值。

public int compareTo(String anotherString) {
   
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;
 
        int k = 0;
        while (k < lim) {
   
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
   
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

hashmap中equals返回true那么compareTo函数应该也返回0?

resize:扩容

扩容条件

作用:初始化和扩容table数组,返回的是Node数组

主要思路:

  1. 先存储旧(未扩容)数组的长度、阈值等

  2. 如果旧数组长度大于0

    如果旧数组长度超过或者等于最大容量限制,不能继续扩容,只能把阈值赋值为最大整型,返回旧数组。

    如果扩容后仍然不超过最大容量限制,就扩容一倍,阈值也翻一倍。

  3. 如果旧数组 为null或者长度等于0

    阈值大于0,阈值就是新数组的大小

    阈值也等于0,就用默认参数来构造新数组

  4. 新阈值计算

  5. 根据新阈值和新容量来new一个新的桶数组。

  6. 把旧桶数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值