[改善Java代码]在明确的场景下,为集合指定初始容量
我们经常使用ArrayList,Vector,Hashmap等集合,一般都是直接用new跟上类名声明出一个集合来,然后使用add,remove,等方法进行操作,而且因为它们是自动管理长度的,所以不用我们特别费心超长问题,这确实是一个非常好的优点,但也有我们需要注意的事项.
下面以ArrayList为例深入了解一下Java是如何实现长度的动态管理的,先从add方法的阅读开始.
 public boolean add(E e) {
         ensureCapacity(size + 1);
         elementData[size++] = e;
         return true;
     }    
我们知道ArrayList是一个大小可变的数组,但它在底层使用的是数组存储(也就是elementData变量),而且数组是定长的,要实现动态长度必然要进行长度的扩展,ensureCapacity方法提供了此功能,代码如下:
     public void ensureCapacity(int minCapacity) {
         modCount++;         //修改计数器
         int oldCapacity = elementData.length;
         //当前需要的长度超过了数组长度,进行扩容处理
         if (minCapacity > oldCapacity) {
             Object oldData[] = elementData;
             //新的容量 = 旧容量 * 1.5 + 1
             int newCapacity = (oldCapacity * 3)/2 + 1;
                 if (newCapacity < minCapacity)
                     newCapacity = minCapacity;
           //数组拷贝,生成新的数组
           elementData = Arrays.copyOf(elementData, newCapacity);
         }
     }  
注意看新数组的长度计算方法,并不是增加一个元素,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的无参构造:
// ArrayList无参构造函数。默认容量是10。
public ArrayList() {
this(10);
}
// ArrayList带容量大小的构造函数。
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
// 新建一个数组
this.elementData = new Object[initialCapacity];
}
默认初始化时声明了一个长度为10的数组 在通过add方法增加第11个元素时,ArrayList类就自动扩展了,新的elementData数组长度就是(10*3)/2 +1 也就是16,当增加到第17个元素时再次扩容为(16*3)/2+1 也就是25,以此类推,实现了ArrayList的动态数组管理.
[改善Java代码]在明确的场景下,为集合指定初始容量的更多相关文章
- Java提高篇(三五)-----Java集合细节(一):请为集合指定初始容量
		
集合是我们在Java编程中使用非常广泛的,它就像大海,海纳百川,像万能容器,盛装万物,而且这个大海,万能容器还可以无限变大(如果条件允许).当这个海.容器的量变得非常大的时候,它的初始容量就会显得很重 ...
 - 改善java程序的151个建议--数组和集合
		
60.性能考虑,数组是首选,在基本类型处理方面.数组还是占优势的,并且集合类的底层也都是通过数组实现.建议在性能要求较高的场景中使用数组替代集合. 61.假设有必要.使用变长数组:我们能够通过对数组扩 ...
 - Java中间(三十五)-----Java详细设置(一个):请指定初始容量设置
		
集合是我们在Java编程中使用很广泛的,它就像大海,海纳百川,像万能容器,盛装万物.并且这个大海,万能容器还能够无限变大(假设条件同意). 当这个海.容器的量变得很大的时候,它的初始容量就会显得很重要 ...
 - JAVA代码设置selector不同状态下的背景
		
Selector设置button点击效果(详细)以及常见问题https://www.jianshu.com/p/a0ddba6d7969 Android 代码动态设置TextView的背景.颜色Sel ...
 - [改善Java代码]使用构造块精炼程序
		
建议36: 使用构造代码块精炼程序 什么叫代码块(Code Block)?用大括号把多行代码封装在一起,形成一个独立的数据体,实现特定算法的代码集合即为代码块,一般来说代码块是不能单独运行的,必须要有 ...
 - [改善Java代码]正确使用String,StringBuffer,StringBuilder
		
CharSequence接口有三个实现类与字符串有关:String,StringBuffer,StringBuffer.虽然它们都与字符串有关,但是其处理机制是不同的. String类是不可改变的量, ...
 - [改善Java代码]易变业务使用脚本语言编写
		
建议16: 易变业务使用脚本语言编写 Java世界一直在遭受着异种语言的入侵,比如PHP.Ruby.Groovy.JavaScript等,这些“入侵者”都有一个共同特征:全是同一类语言—脚本语言,它们 ...
 - [改善Java代码]不同的场景使用不同的泛型通配符
		
Java泛型支持通配符(Wildcard),可以单独使用一个"?"表示任意类,也可以使用extends关键字标识某一类(接口)的子类型,还可以使用super关键字标识某一类(接口) ...
 - [改善Java代码]不同的列表选择不同的遍历方法
		
一.场景: 我们来看一个场景,统计一个省的各科高考科目考试的平均分. 当然使用数据库中的一个SQL语句就能求出平均值,不过这个不再我们的考虑之列,这里只考虑使用纯Java的方式来解决.(由于我的机器配 ...
 
随机推荐
- struts2+Hibernate4+spring3+EasyUI环境搭建之四:引入hibernate4以及spring3与hibernate4整合
			
1.导入hibernate4 jar包:注意之前引入的struts2需要排除javassist 否则冲突 <!-- hibernate4 --> <dependency> & ...
 - Linux递归删除文件命令
			
Linux递归删除文件命令 find . -name "*.log.*" -exec ls {} \; find . -name "*.log.*" -exec ...
 - jquery easyui添加图标扩展
			
easyui中有很多通过iconCls="icon-reload"这样的属性引入小图标显示,当然我们也可以自己添加自己的小图标. 方式:1.我们可以在jquery easyui的文 ...
 - Windows Server 2003 R2 64位简体中文版下载
			
32位版 CD1: SHA1值:d0dd2782e9387328ebfa45d8804b6850acabf520 ed2k://|file|cn_win_srv_2003_r2_enterprise_ ...
 - Umbraco官方技术文档 中文翻译
			
Umbraco 官方技术文档中文翻译 http://blog.csdn.net/u014183619/article/details/51919973 http://www.cnblogs.com/m ...
 - 一、Microsoft Dynamics CRM 4.0 SDK概述
			
Chapter 1. Microsoft Dynamics CRM 4.0 SDK Overview(SDK概述) You are probably reading this book because ...
 - 命令行刷机教程( 以Linux系统为例 )
			
//第一步adb device // 如果不能cd AndroidSDK/platform-toolsadb kill-server adb start-server //第二步adb reboot ...
 - pygame “音乐盒”---- 播放一首歌& 点击对话框后背景以及对话框大小改变
			
有时,你用pygame写的游戏也许需要播放一些背景音乐,该怎么做呢,直接上代码: 下面的代码,有关于: 1>设置对话框图标.大小.标题 2>播放音乐 3>设置背景图片,以及获取背景图 ...
 - php 建立类POST/GET 的HTTP请求
			
1.第一种利用fsock的方式来建立类POST的请求. <?php $srv_ip = '192.168.1.5';//你的目标服务地址. $srv_port = 80;//端口 $url = ...
 - 【转】The Zen of Python
			
http://www.python.org/dev/peps/pep-0020/ Beautiful is better than ugly. Explicit is better than impl ...