关于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 注意:没有扩容 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述