在明确的场景下,为集合指定初始容量

简介:

我们经常使用ArrayList,Vector,Hashmap等集合,一般都是直接用new跟上类名声明出一个集合来,然后使用add,remove,等方法进行操作,而且因为它们是自动管理长度的,所以不用我们特别费心超长问题,这确实是一个非常好的优点,但也有我们需要注意的事项.

下面以ArrayList为例深入了解一下Java是如何实现长度的动态管理的,先从add方法的阅读开始.

复制代码
1 public boolean add(E e) {    
2         ensureCapacity(size + 1);     
3         elementData[size++] = e;    
4         return true;    
5     }    
复制代码

我们知道ArrayList是一个大小可变的数组,但它在底层使用的是数组存储(也就是elementData变量),而且数组是定长的,要实现动态长度必然要进行长度的扩展,ensureCapacity方法提供了此功能,代码如下:

复制代码
 1     public void ensureCapacity(int minCapacity) {    
 2         modCount++;         //修改计数器  
 3         int oldCapacity = elementData.length;      
 4         //当前需要的长度超过了数组长度,进行扩容处理  
 5         if (minCapacity > oldCapacity) {    
 6             Object oldData[] = elementData;    
 7             //新的容量 = 旧容量 * 1.5 + 1  
 8             int newCapacity = (oldCapacity * 3)/2 + 1;    
 9                 if (newCapacity < minCapacity)    
10                     newCapacity = minCapacity;    
11           //数组拷贝,生成新的数组   
12           elementData = Arrays.copyOf(elementData, newCapacity);    
13         }    
14     }  
复制代码

注意看新数组的长度计算方法,并不是增加一个元素,elementData的长度就加1,而是在达到了elementData长度的临界点时,才将elementData扩容1.5把倍,这样实现有什么好处呢?好处就是避免了多次调用copyOf()方法的性能开销,否则每增加一个元素都要扩容一次,那性能岂不是非常的糟糕.

为什么是1.5倍呢,因为一次扩容太大,占用的内存也就越大,浪费的内存也就越多(1.5倍扩容,最多浪费33%的数组空间,而2.5倍扩容则最多浪费60%的内存),而扩容太小(比如每次扩容1.1倍),则需要多次对数组重新分配内存,性能消耗严重,经过测试验证,扩容1.5倍即满足了性能要求,也减少了内存消耗.

elementData的默认长度是10,如果我们使用默认的方式生命ArrayList,如new ArrayList(),则elementData的初始长度就是10.我们来看ArrayList的无参构造:

复制代码
 1     // ArrayList无参构造函数。默认容量是10。    
 2     public ArrayList() {    
 3         this(10);    
 4     }    
 5     // ArrayList带容量大小的构造函数。    
 6     public ArrayList(int initialCapacity) {    
 7         super();    
 8         if (initialCapacity < 0)    
 9             throw new IllegalArgumentException("Illegal Capacity: "+    
10                                                initialCapacity);    
11         // 新建一个数组    
12         this.elementData = new Object[initialCapacity];    
13     }  
复制代码

默认初始化时声明了一个长度为10的数组 在通过add方法增加第11个元素时,ArrayList类就自动扩展了,新的elementData数组长度就是(10*3)/2 +1 也就是16,当增加到第17个元素时再次扩容为(16*3)/2+1 也就是25,以此类推,实现了ArrayList的动态数组管理.

 


本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/5422175.html,如需转载请自行联系原作者

相关文章
|
存储 缓存 内存技术
USB容量大小对传输速度影响有多大
USB容量大小对传输速度影响有多大
USB容量大小对传输速度影响有多大
|
存储 运维 负载均衡
Redis Cluster集群原理+三主三从交叉复制实战+故障切换
Redis Cluster集群原理+三主三从交叉复制实战+故障切换
2389 0
Redis Cluster集群原理+三主三从交叉复制实战+故障切换
|
前端开发 API C#
c#实现简单Token口令验证
  最近一个项目发现手机验证码总是被人盗刷,一秒钟刷了1百多个,很明显这种行为是通过软件自动提交的,自动发帖机原理类似,解决这个问题目前有两个方案。   出现这个问题原因:请求手机验证码Api时没有任何带任何验证,只要请求了手机号正确就执行发送操作,软件或代码很容易伪造请求过程。   解决方案有很多种,可以选择下面一种或几种组合起来使用。   方案1:用户获取手机验证码时候弹出图片验证码,输入后再发送。
1890 0
热电材料:温差发电的绿色能源技术
【10月更文挑战第17天】温差发电技术利用热电材料将热能直接转换为电能,具有环境友好和高效的特点。本文介绍了热电材料的基础知识、温差发电的工作原理及应用案例,包括人体体温发电、海洋温差发电和工业余热利用,并展望了热电材料的未来发展。
|
机器学习/深度学习 存储 人工智能
AllData数据中台核心菜单九:元数据管理
杭州奥零数据科技有限公司成立于2023年,专注于数据中台业务,维护开源项目AllData并提供商业版解决方案。AllData提供数据集成、存储、开发、治理及BI展示等一站式服务,支持AI大模型应用,助力企业高效利用数据价值。
|
存储 编译器 C语言
C语言之字符串与字符数组的区别
​ 1.字符串的定义: (1)单个字符: char ch='i';//单个字符的定义 (2)一维字符串数组: char arr[]="love";(这种方法定义的一维字符串数组必须赋值) char arr[4];(想内存申请创建可以存储3个字符的数组空间) char arr[5]=”love”;(开辟5个字节的空间存放字符love,最后一个字节存放'\0'字符) char arr[5]={'l','o',v','e'};(开辟5个字节的空间存放字符love,最后一个字节存放'\0'字符) 2.字符串长度 3.字符串和字符数组的区别: 由于C语言中没有string关键字,所以不能定义字符串
568 0
C语言之字符串与字符数组的区别
|
缓存 API 开发工具
Unity——工程与资源
Unity——工程与资源
637 1
|
弹性计算 负载均衡 对象存储
阿里云免费云服务器:个人用户每月750小时免费,企业用户
阿里云免费云服务器:个人用户每月750小时免费,企业用户u1服务器2核8GB免费使用3个月
663 0
|
机器学习/深度学习 人工智能 编解码
【前沿技术RPA】 一文学会用UiPath实现PDF自动化
UiPath在传统的RPA(Robotic process automation)的基础上,增加了See(AI通过计算机视觉阅读用户的计算机屏幕)和Think(通过机器学习来发现平台能够为用户构建什么自动化流程)从而不断帮助用户自动化构建流程,而不仅仅是用户自主发现,自主构建。并且在构建的过程当中,做到了Low-code甚至是No-code的程度,让每一位员工都可以自主使用。
【前沿技术RPA】 一文学会用UiPath实现PDF自动化
|
人工智能 达摩院 自然语言处理
阿里AI实现全球首个实时翻译直播,214种语言翻译支持今年双11
10月21日,阿里完成全球首个多语言实时翻译的电商直播,该直播展示了AI无惧嘈杂环境、口音不标准及口语化语言风格等问题,实时将中文直播内容精准翻译成英语、俄语、西班牙语等语言。阿里方面透露,该技术将大规模应用于2020双11。
48705 0
阿里AI实现全球首个实时翻译直播,214种语言翻译支持今年双11