博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Map<String, String> m3 = new HashMap<>(3); 申请了多大的数组空间
阅读量:6588 次
发布时间:2019-06-24

本文共 3243 字,大约阅读时间需要 10 分钟。

  hot3.png

1、先看结果

Map
m0 = new HashMap<>(0);// 不创建内部存储数组 m0.put("k","v");// 内部空间开辟了 1 (数组长度=1) Map
m1 = new HashMap<>(1);// 不创建内部存储数组 m1.put("k","v");// 内部空间开辟了 1 (数组长度=1) Map
m2 = new HashMap<>(2);// 不创建内部存储数组 m2.put("k","v");// 内部空间开辟了 2 (数组长度=2) Map
m3 = new HashMap<>(3);// 不创建内部存储数组 m3.put("k","v");// 内部空间开辟了 4 (数组长度=4)

首先,我们应该知道HashMap内部是用数组存储数据的。

没错,下面这句话,是不创建数组的,所以结论是 0

Map
m3 = new HashMap<>(3);

2、为什么是0?

new HashMap<>(3) 只是设置了threshold(扩容阈值)和loadFactor 加载因子,请看代码

public HashMap(int initialCapacity, float loadFactor) {        if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal initial capacity: " +                                               initialCapacity);        if (initialCapacity > MAXIMUM_CAPACITY)            initialCapacity = MAXIMUM_CAPACITY;        if (loadFactor <= 0 || Float.isNaN(loadFactor))            throw new IllegalArgumentException("Illegal load factor: " +                                               loadFactor);        this.loadFactor = loadFactor;        threshold = initialCapacity;        init();    }

3、什么时候创建数组?

只有调用put的方法的时候才真正的创建数组,具体创建多大的数组呢?从上面的代码可以看出m3 创建了 长度=4的数组

public V put(K key, V value) {        if (table == EMPTY_TABLE) {            inflateTable(threshold); // 这句话会去创建数组        }        if (key == null)            return putForNullKey(value);        int hash = hash(key);        int i = indexFor(hash, table.length);        for (Entry
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; } } modCount++; addEntry(hash, key, value, i); return null; }

4、数组的长度为什么不是3?

k=数组长度-1,因为要保证k这个值的二进制全是1,所以new HashMap(3),实际数组长度=4,这样k=3,k的二进制值:11

如果new HashMap(5),内部数组长度=8, k=7,k的二进制:111

private void inflateTable(int toSize) {        // Find a power of 2 >= toSize        int capacity = roundUpToPowerOf2(toSize); // 这句话保证了k(k=数组长度capacity-1)的二进制值全是1        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);        table = new Entry[capacity];        initHashSeedAsNeeded(capacity);    }

5、分析roundUpToPowerOf2方法

private static int roundUpToPowerOf2(int number) {        // assert number >= 0 : "number must be non-negative";        return number >= MAXIMUM_CAPACITY                ? MAXIMUM_CAPACITY                : (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;    }

p = number-1 ,然后左移一位p<<1, Integer.highestOneBit(p),获取最高位,其他位都是0

例子:number=3,p=(二级制0010),p左移一位等于4(二级制0100),然后获取最高位的结果是4(二级制100)

 number=6,p=5(二级制0101),p左移一位等于10(二级制1010),然后获取最高位的结果是8(二级制1000)

这样就可以的结果就可以保证k的二级制都是1了

6、为什么要保证k的二进制全是1?

static int indexFor(int h, int length) {        // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";        return h & (length-1);    }

因为要根据hash 值来索引,当前数据存放在哪个下标数组里,同时还不能越界,如上代码,把hash和length-1 进行一下与操作,就能找到该数据存放的下标,同时还不越界。

 

分析的jdk版本jdk7_75

如有不对,请指出!谢谢

转载于:https://my.oschina.net/huangy/blog/1615680

你可能感兴趣的文章
玩转iOS转场动画
查看>>
机房(厂房)温度环境监控系统
查看>>
spark-shell开发wordcount程序
查看>>
DNS正反解析
查看>>
数据库与监控安全
查看>>
算法研发---对宏定义#define相关研究
查看>>
Linux下搭建FTP服务器
查看>>
浅析Mysql的隔离级别及MVCC
查看>>
1.3 Shell脚本编程基础之条件测试
查看>>
JAVA程序员代表大众车,C++程序员代表捷豹,看看各类程序员们代表着什么车
查看>>
centOS7下安装GUI图形界面
查看>>
postgresql 中int4rang类型项目应用
查看>>
postfix疯狂外发垃圾邮件之分析与解决
查看>>
test和read命令
查看>>
ubuntu无法激活输入法,Zendstudio无法激活中文输入法问题
查看>>
《使命召唤7:黑色行动》有什么简单办法进入僵尸模式
查看>>
ChannelOption.TCP_NODELAY, true->浅谈tcp_nodelay的作用
查看>>
UEFI win7系统的安装
查看>>
Oracle 补丁体系 及 opatch 工具 介绍
查看>>
java的内部字符编码
查看>>