Java集合系列[1]----ArrayList源码分析
2018-06-18 03:51:42来源:未知 阅读 ()
本篇分析ArrayList的源码,在分析之前先跟大家谈一谈数组。数组可能是我们最早接触到的数据结构之一,它是在内存中划分出一块连续的地址空间用来进行元素的存储,由于它直接操作内存,所以数组的性能要比集合类更好一些,这是使用数组的一大优势。但是我们知道数组存在致命的缺陷,就是在初始化时必须指定数组大小,并且在后续操作中不能再更改数组的大小。在实际情况中我们遇到更多的是一开始并不知道要存放多少元素,而是希望容器能够自动的扩展它自身的容量以便能够存放更多的元素。ArrayList就能够很好的满足这样的需求,它能够自动扩展大小以适应存储元素的不断增加。它的底层是基于数组实现的,因此它具有数组的一些特点,例如查找修改快而插入删除慢。本篇我们将深入源码看看它是怎样对数组进行封装的。首先看看它的成员变量和三个主要的构造器。
1 //默认初始化容量 2 private static final int DEFAULT_CAPACITY = 10; 3 4 //空对象数组 5 private static final Object[] EMPTY_ELEMENTDATA = {}; 6 7 //对象数组 8 private transient Object[] elementData; 9 10 //集合元素个数 11 private int size; 12 13 //传入初始容量的构造方法 14 public ArrayList(int initialCapacity) { 15 super(); 16 if (initialCapacity < 0) { 17 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); 18 } 19 //新建指定容量的Object类型数组 20 this.elementData = new Object[initialCapacity]; 21 } 22 23 //不带参数的构造方法 24 public ArrayList() { 25 super(); 26 //将空的数组实例传给elementData 27 this.elementData = EMPTY_ELEMENTDATA; 28 } 29 30 //传入外部集合的构造方法 31 public ArrayList(Collection<? extends E> c) { 32 //持有传入集合的内部数组的引用 33 elementData = c.toArray(); 34 //更新集合元素个数大小 35 size = elementData.length; 36 //判断引用的数组类型, 并将引用转换成Object数组引用 37 if (elementData.getClass() != Object[].class) { 38 elementData = Arrays.copyOf(elementData, size, Object[].class); 39 } 40 }
可以看到ArrayList的内部存储结构就是一个Object类型的数组,因此它可以存放任意类型的元素。在构造ArrayList的时候,如果传入初始大小那么它将新建一个指定容量的Object数组,如果不设置初始大小那么它将不会分配内存空间而是使用空的对象数组,在实际要放入元素时再进行内存分配。下面再看看它的增删改查方法。
1 //增(添加) 2 public boolean add(E e) { 3 //添加前先检查是否需要拓展数组, 此时数组长度最小为size+1 4 ensureCapacityInternal(size + 1); 5 //将元素添加到数组末尾 6 elementData[size++] = e; 7 return true; 8 } 9 10 11 //增(插入) 12 public void add(int index, E element) { 13 //插入位置范围检查 14 rangeCheckForAdd(index); 15 //检查是否需要扩容 16 ensureCapacityInternal(size + 1); 17 //挪动插入位置后面的元素 18 System.arraycopy(elementData, index, elementData, index + 1, size - index); 19 //在要插入的位置赋上新值 20 elementData[index] = element; 21 size++; 22 } 23 24 //删 25 public E remove(int index) { 26 //index不能大于size 27 rangeCheck(index); 28 modCount++; 29 E oldValue = elementData(index); 30 int numMoved = size - index - 1; 31 if (numMoved > 0) { 32 //将index后面的元素向前挪动一位 33 System.arraycopy(elementData, index+1, elementData, index, numMoved); 34 } 35 //置空引用 36 elementData[--size] = null; 37 return oldValue; 38 } 39 40 //改 41 public E set(int index, E element) { 42 //index不能大于size 43 rangeCheck(index); 44 E oldValue = elementData(index); 45 //替换成新元素 46 elementData[index] = element; 47 return oldValue; 48 } 49 50 //查 51 public E get(int index) { 52 //index不能大于size 53 rangeCheck(index); 54 //返回指定位置元素 55 return elementData(index); 56 }
1 private void ensureCapacityInternal(int minCapacity) { 2 //如果此时还是空数组 3 if (elementData == EMPTY_ELEMENTDATA) { 4 //和默认容量比较, 取较大值 5 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 6 } 7 //数组已经初始化过就执行这一步 8 ensureExplicitCapacity(minCapacity); 9 } 10 11 private void ensureExplicitCapacity(int minCapacity) { 12 modCount++; 13 //如果最小容量大于数组长度就扩增数组 14 if (minCapacity - elementData.length > 0) { 15 grow(minCapacity); 16 } 17 } 18 19 //集合最大容量 20 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 21 22 //增加数组长度 23 private void grow(int minCapacity) { 24 //获取数组原先的容量 25 int oldCapacity = elementData.length; 26 //新数组的容量, 在原来的基础上增加一半 27 int newCapacity = oldCapacity + (oldCapacity >> 1); 28 //检验新的容量是否小于最小容量 29 if (newCapacity - minCapacity < 0) { 30 newCapacity = minCapacity; 31 } 32 //检验新的容量是否超过最大数组容量 33 if (newCapacity - MAX_ARRAY_SIZE > 0) { 34 newCapacity = hugeCapacity(minCapacity); 35 } 36 //拷贝原来的数组到新数组 37 elementData = Arrays.copyOf(elementData, newCapacity); 38 }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:jBPM7.5 中文文档——概述
下一篇:Spring boot入门篇
- 国外程序员整理的Java资源大全(全部是干货) 2020-06-12
- Spring系列.ApplicationContext接口 2020-06-11
- 2020年深圳中国平安各部门Java中级面试真题合集(附答案) 2020-06-11
- 2020年java就业前景 2020-06-11
- 04.Java基础语法 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash