IdentityHashMap

IdentityHashMap是一个特殊的Map,它使用对象的引用而非equals方法来判断key是否相等。其内部通过hash函数确保key落在偶数索引,实现key-value对的存储。负载因子为2/3,当元素超过容量的2/3时会进行扩容。构造函数允许指定初始容量,且最大容量为2^29。文章详细解析了IdentityHashMap的属性和hash计算方式。
摘要由CSDN通过智能技术生成

前言

传统map中要求key的判断是equals,当我们想用对象作为key,并且需要地址相同时才能认为是相等的,这样传统map做不了,我们就要打破这一规定,比较key值用==

  • 为一组易变的对象维护代理对象
  • 基于一个对象的引用建立一个快速缓存
  • 保持一个有引用的对象的内存图

属性

/*
*
* 负载因子2/3,超过21的时候就要扩容,这个21也许是性能最佳点,所以指定21,
* 推算出32
*/
private static final int DEFAULT_CAPACITY = 32;
/*
* 最小扩容4,负载因子是2/3,最小4的时候,超过2就会扩容
*/
private static final int MINIMUM_CAPACITY = 4;
/*
*最大容量,2^31-1,要2次幂,2^30,但是key,value都在table中,所以它
* 只能装下hashMap一半的元素2^29
*/
private static final int MAXIMUM_CAPACITY = 1 << 29;

hash

确保hash是偶数,这样与运算长度,就能确保key落在偶数索引。这样在table中,偶数是key,vlue在奇数上,避免出现下面的情况:
在这里插入图片描述

private static int hash(Object x, int length) {
        int h = System.identityHashCode(x);
        // Multiply by -254 to use the hash LSB and to ensure index is even
        //相当于乘以-254,确保hash值是偶数,左移1位就可以保证
        return ((h << 1) - (h << 8)) & (length - 1);
    }

在这里插入图片描述
(h << 1) - (h << 8)确保了最后一位是0,决定了hash值是偶数,这样key只会在偶数索引上(最后一位是0,和任何数&运算都是偶数),然后低8位除去最后一位前7位都得以保留,其他位混合,这样更有利于Hash均匀。

构造函数

public IdentityHashMap() {
//无参构造,默认32
        init(DEFAULT_CAPACITY);
    }
public IdentityHashMap(int expectedMaxSize) {
//指定大小,如果小于0,抛出非法参数错误
        if (expectedMaxSize < 0)
            throw new IllegalArgumentException("expectedMaxSize is negative: "
                                               + expectedMaxSize);
        init(capacity(expectedMaxSize));
    }
//key和value都存储在table,所以指定容量后,实际给table大小是2倍   
private void init(int initCapacity) {
        table = new Object[2 * initCapacity];
    }
//按给定扩容阈值,超过它就会引发扩容  
private static int capacity(int expectedMaxSize) {
        // assert expectedMaxSize >= 0;
        return
 /**扩容阈值大于最大容量的1/3,直接给最大容量2^29创建,否则如果指定容量小于最小容量的
 * 2/3,直接最小容量4。其他则table长度的值就应该是3/2倍的扩容阈值,那应该是1.5倍啊,
 * 怎么是三倍?Integer.highestOneBit返回的是左侧最大2的次幂,已经减半了i - (i >>> 
 * 1),不就是0.5了吗,所以这里直接3倍了
 */
            (expectedMaxSize > MAXIMUM_CAPACITY / 3) ? MAXIMUM_CAPACITY :
            (expectedMaxSize <= 2 * MINIMUM_CAPACITY / 3) ? MINIMUM_CAPACITY :
            Integer.highestOneBit(expectedMaxSize + (expectedMaxSize << 1));
    }      

返回给定值左侧最大的2的次幂
在这里插入图片描述

//获取i最高位1代表的2次幂,最高位1代表的权值
 public static int highestOneBit(int i) {
        // HD, Figure 3-1
        i |= (i >>  1);//将第二高位置1
        i |= (i >>  2);//将第二高位之后的两位置1
        i |= (i >>  4);
        i |= (i >>  8);
        i |= (i >> 16);//所有位都置1了
        //此时的如果i+1就是i右侧最小的2次幂(HashMap)
        return i - (i >>> 1);//i左侧最大的2次幂
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值