关于HashMap、HashSet和ArrayList集合对象容量初始值设置及扩容演示

ArrayList:
-------------------------------------
明确知道容量:直接设置初始容量,如new ArrayList<>(100)
无法确定容量:预估一个比较接近的值,如果实在无法确定,则无需指定初始值 (有默认值)
ArrayList没有加载因子,初始容量10,扩容增量为原来的0.5倍取整


HashMap(HashSet规则相同)
-------------------------------------
HashMap的默认加载因子为0.75,但可以使用构造器指定,如new HashMap<>(100, 1),此时指定加载因子为1
故计算HashMap的初始值时的工式为:(int) (realSize / loadFactor) + 1

如果实际容量为100,加载因子为默认(0.75),计算容量为:(int) (100 / 0.75) + 1 = 134,则实例化HashMap为 new HashMap<>(134)  (注意:由于HashMap的容量必须为2的N次方,故此时HashMap的实际容量为256)
如果实际容量为100,加载因子1,则计算工式为:(int) (100 / 1) + 1 = 101,则则实例化HashMap为 new HashMap<>(101, 1)   (注意:由于HashMap的容量必须为2的N次方,故此时HashMap的实际容量为128)
HashMap、HashMap加载因子0.75,初始容量16,扩容增量为原来的1倍
注意:加载因子越大节省内存但查找效率低,加载因子越小耗内存但查找效率高,系统默认加载因子为0.75,一般情况下我们是无需修改的。

//以下为计算HashMap的实际容量

//计算容量。
int capacity = (int) (realSize / loadFactor) + 1;
//必须为2的N次方并进行上舍入。
int pow = (int)Math.ceil( Math.log(capacity) / Math.log(2.0));
//返回2的N次方为实际容量。
return (int) Math.pow(2, pow);

 

 

以上单元测试HashMap、ArrayList持续增加元素及扩容情况:

复制代码
    @Test
    public void testHashMapResize() throws Exception {
        System.out.println("-------- 开始测试HashMap --------");
        System.out.println("不设置 initCapacity");
        this.testHashMapResizeProfile(0);
        System.out.println("");
        System.out.println("initCapacity 为 25");
        this.testHashMapResizeProfile(25);
        System.out.println("");
        System.out.println("initCapacity 为 34");
        this.testHashMapResizeProfile(34);

        System.out.println();
        System.out.println("-------- 开始测试ArrayList --------");
        System.out.println("不设置 initCapacity");
        this.testArrayListResizeProfile(0);
        System.out.println("");
        System.out.println("initCapacity 为 25");
        this.testArrayListResizeProfile(25);
    }

    /**
     * 以循环添加25个元素测试扩容。
     * @param initCapacity 初始容量
     * @throws Exception
     */
    private void testHashMapResizeProfile(int initCapacity) throws Exception {
        Map<String, String> map = null;
        if (initCapacity <= 0) {
            map = new HashMap();
        } else {
            map = new HashMap(initCapacity);
        }

        Field threshold = map.getClass().getDeclaredField("threshold");
        Field size = map.getClass().getDeclaredField("size");
        Method capacity = map.getClass().getDeclaredMethod("capacity");

        threshold.setAccessible(true);
        size.setAccessible(true);
        capacity.setAccessible(true);

        // 临界值、容量测试
        for (int i = 1; i <= 25; i++) {
            map.put(String.valueOf(i), i + "**");
            System.out.println("第" + i + "个对象, size为" + size.get(map) + ", threshold为" + threshold.get(map) + ", capacity容量为" + capacity.invoke(map));
        }
    }

    /**
     * 以循环添加25个元素测试扩容。
     * @param initCapacity 初始容量
     * @throws Exception
     */
    private void testArrayListResizeProfile(int initCapacity) throws Exception {
        ArrayList<String> list = null;
        if (initCapacity <= 0) {
            list = new ArrayList();
        } else {
            list = new ArrayList(initCapacity);
        }

        Field size = list.getClass().getDeclaredField("size");
        Field elementData = list.getClass().getDeclaredField("elementData");

        size.setAccessible(true);
        elementData.setAccessible(true);

        // 临界值、容量测试
        for (int i = 1; i <= 25; i++) {
            list.add(String.valueOf(i));
            System.out.println("第" + i + "个对象, size为:" + size.get(list) + ", 扩容后容量为:" + ((Object[])elementData.get(list)).length);
        }
    }
复制代码

 

以下为HashMap持续增加元素及扩容输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
不设置 initCapacity
1个对象, size为1, threshold为12, capacity容量为16
2个对象, size为2, threshold为12, capacity容量为16
3个对象, size为3, threshold为12, capacity容量为16
4个对象, size为4, threshold为12, capacity容量为16
5个对象, size为5, threshold为12, capacity容量为16
6个对象, size为6, threshold为12, capacity容量为16
7个对象, size为7, threshold为12, capacity容量为16
8个对象, size为8, threshold为12, capacity容量为16
9个对象, size为9, threshold为12, capacity容量为16
10个对象, size为10, threshold为12, capacity容量为16
11个对象, size为11, threshold为12, capacity容量为16
12个对象, size为12, threshold为12, capacity容量为16
13个对象, size为13, threshold为24, capacity容量为32
14个对象, size为14, threshold为24, capacity容量为32
15个对象, size为15, threshold为24, capacity容量为32
16个对象, size为16, threshold为24, capacity容量为32
17个对象, size为17, threshold为24, capacity容量为32
18个对象, size为18, threshold为24, capacity容量为32
19个对象, size为19, threshold为24, capacity容量为32
20个对象, size为20, threshold为24, capacity容量为32
21个对象, size为21, threshold为24, capacity容量为32
22个对象, size为22, threshold为24, capacity容量为32
23个对象, size为23, threshold为24, capacity容量为32
24个对象, size为24, threshold为24, capacity容量为32
25个对象, size为25, threshold为48, capacity容量为64
注意:扩容2
 
initCapacity 为 25
1个对象, size为1, threshold为24, capacity容量为32
2个对象, size为2, threshold为24, capacity容量为32
3个对象, size为3, threshold为24, capacity容量为32
4个对象, size为4, threshold为24, capacity容量为32
5个对象, size为5, threshold为24, capacity容量为32
6个对象, size为6, threshold为24, capacity容量为32
7个对象, size为7, threshold为24, capacity容量为32
8个对象, size为8, threshold为24, capacity容量为32
9个对象, size为9, threshold为24, capacity容量为32
10个对象, size为10, threshold为24, capacity容量为32
11个对象, size为11, threshold为24, capacity容量为32
12个对象, size为12, threshold为24, capacity容量为32
13个对象, size为13, threshold为24, capacity容量为32
14个对象, size为14, threshold为24, capacity容量为32
15个对象, size为15, threshold为24, capacity容量为32
16个对象, size为16, threshold为24, capacity容量为32
17个对象, size为17, threshold为24, capacity容量为32
18个对象, size为18, threshold为24, capacity容量为32
19个对象, size为19, threshold为24, capacity容量为32
20个对象, size为20, threshold为24, capacity容量为32
21个对象, size为21, threshold为24, capacity容量为32
22个对象, size为22, threshold为24, capacity容量为32
23个对象, size为23, threshold为24, capacity容量为32
24个对象, size为24, threshold为24, capacity容量为32
25个对象, size为25, threshold为48, capacity容量为64
注意:扩容1
 
initCapacity 为 34   (int) (25 / 0.75) + 1 = 34
1个对象, size为1, threshold为48, capacity容量为64
2个对象, size为2, threshold为48, capacity容量为64
3个对象, size为3, threshold为48, capacity容量为64
4个对象, size为4, threshold为48, capacity容量为64
5个对象, size为5, threshold为48, capacity容量为64
6个对象, size为6, threshold为48, capacity容量为64
7个对象, size为7, threshold为48, capacity容量为64
8个对象, size为8, threshold为48, capacity容量为64
9个对象, size为9, threshold为48, capacity容量为64
10个对象, size为10, threshold为48, capacity容量为64
11个对象, size为11, threshold为48, capacity容量为64
12个对象, size为12, threshold为48, capacity容量为64
13个对象, size为13, threshold为48, capacity容量为64
14个对象, size为14, threshold为48, capacity容量为64
15个对象, size为15, threshold为48, capacity容量为64
16个对象, size为16, threshold为48, capacity容量为64
17个对象, size为17, threshold为48, capacity容量为64
18个对象, size为18, threshold为48, capacity容量为64
19个对象, size为19, threshold为48, capacity容量为64
20个对象, size为20, threshold为48, capacity容量为64
21个对象, size为21, threshold为48, capacity容量为64
22个对象, size为22, threshold为48, capacity容量为64
23个对象, size为23, threshold为48, capacity容量为64
24个对象, size为24, threshold为48, capacity容量为64
25个对象, size为25, threshold为48, capacity容量为64
注意:未扩容

 

以下为ArrayList持续增加元素及扩容输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
不设置 initCapacity
1个对象, size为:1, 扩容后容量为:10
2个对象, size为:2, 扩容后容量为:10
3个对象, size为:3, 扩容后容量为:10
4个对象, size为:4, 扩容后容量为:10
5个对象, size为:5, 扩容后容量为:10
6个对象, size为:6, 扩容后容量为:10
7个对象, size为:7, 扩容后容量为:10
8个对象, size为:8, 扩容后容量为:10
9个对象, size为:9, 扩容后容量为:10
10个对象, size为:10, 扩容后容量为:10
11个对象, size为:11, 扩容后容量为:15
12个对象, size为:12, 扩容后容量为:15
13个对象, size为:13, 扩容后容量为:15
14个对象, size为:14, 扩容后容量为:15
15个对象, size为:15, 扩容后容量为:15
16个对象, size为:16, 扩容后容量为:22
17个对象, size为:17, 扩容后容量为:22
18个对象, size为:18, 扩容后容量为:22
19个对象, size为:19, 扩容后容量为:22
20个对象, size为:20, 扩容后容量为:22
21个对象, size为:21, 扩容后容量为:22
22个对象, size为:22, 扩容后容量为:22
23个对象, size为:23, 扩容后容量为:33
24个对象, size为:24, 扩容后容量为:33
25个对象, size为:25, 扩容后容量为:33
注意:扩容2次initCapacity 为 25
1个对象, size为:1, 扩容后容量为:25
2个对象, size为:2, 扩容后容量为:25
3个对象, size为:3, 扩容后容量为:25
4个对象, size为:4, 扩容后容量为:25
5个对象, size为:5, 扩容后容量为:25
6个对象, size为:6, 扩容后容量为:25
7个对象, size为:7, 扩容后容量为:25
8个对象, size为:8, 扩容后容量为:25
9个对象, size为:9, 扩容后容量为:25
10个对象, size为:10, 扩容后容量为:25
11个对象, size为:11, 扩容后容量为:25
12个对象, size为:12, 扩容后容量为:25
13个对象, size为:13, 扩容后容量为:25
14个对象, size为:14, 扩容后容量为:25
15个对象, size为:15, 扩容后容量为:25
16个对象, size为:16, 扩容后容量为:25
17个对象, size为:17, 扩容后容量为:25
18个对象, size为:18, 扩容后容量为:25
19个对象, size为:19, 扩容后容量为:25
20个对象, size为:20, 扩容后容量为:25
21个对象, size为:21, 扩容后容量为:25
22个对象, size为:22, 扩容后容量为:25
23个对象, size为:23, 扩容后容量为:25
24个对象, size为:24, 扩容后容量为:25
25个对象, size为:25, 扩容后容量为:25
注意:没有扩容

 

 

 

 

 

posted @   有容乃大  阅读(1796)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示