数据结构之ArrayList
Posted pridelory
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构之ArrayList相关的知识,希望对你有一定的参考价值。
一、先说几句废话
在java中,线性结构的代表就是List,List下分为ArrayList和LinkedList两种不同的存储结构。本偏说ArrayList,其是用数组实现的,所以具有数组的随机访问功能,所以查询或更新的速度很快。而对于插入和删除操作可能都需要移动大量的元素,所以ArrayList的插入删除操作的效率不高。
二、源码(JDK10)
1、ArrayList集合的初始化。
ArrayList底层是以数组作为载体的,所以首先得有个数组
transient Object[] elementData;
这就是ArrayList保存元素的载体,数组的容量capacity就是这个数组的长度
private int size;
此size代表此ArrayList中已有的元素的个数,要和capacity做一个区分,size <= capacity
接下来说初始化
//当无参构造时的默认容量 private static final int DEFAULT_CAPACITY = 10; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //无参初始化 public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //带参初始化 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
可见当无参初始化的时候,直接把elementData置空。当指定初始容量初始化时候,如果其大于零,那么会直接创建一个指定容量的数组,一步到位。
到这一步可能发现不了两者方式有何不同,但是当增加元素后就恍然大悟了,且看如下。
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
//当增加一个元素后,判断当前元素是否达到容量,如果没达到,则直接添加,否则要进行扩容操作grow()
private void add(E e, Object[] elementData, int s) { if (s == elementData.length) elementData = grow(); elementData[s] = e; size = s + 1; }
//每次扩容后的容量至少当前元素个数+1 private Object[] grow() { return grow(size + 1); } private Object[] grow(int minCapacity) { return elementData = Arrays.copyOf(elementData, newCapacity(minCapacity)); }
private int newCapacity(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); //默认扩容1.5倍 if (newCapacity - minCapacity <= 0) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) //空构造扩容必经之步 return Math.max(DEFAULT_CAPACITY, minCapacity); if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return minCapacity; } return (newCapacity - MAX_ARRAY_SIZE <= 0) ? newCapacity : hugeCapacity(minCapacity); }
(1)当无参数初始化时,增加一个元素。显然肯定满足扩容条件,进行扩容,由代码可见无参数构造的ArrayList当增加第一个元素的时候,容量先会被扩大到默认的10(DEFAULT_CAPACITY),随后添加当元素当个数达到9时,此时再添加那么容量就会再次扩容到15。如此往复
(2) 当指定参数初始化时,那么当元素个数快达到容量时,就会进行扩容。
说明:1、每次扩容的过程伴随着数组的复制,这会产生一定的时间。 2、每次扩容是根据老的容量用右移计算新的容量,因为右移运算符速度快。
对比一下:现在预计要添加1000个元素,如果通过无参构造生成ArrayList的话,那么在后续过程中会扩容13此才能完成存储。如果是有参构造函数并且一开始默认赋值1001的话,此时就会在初始化时候直接分配1001个空间,从而避免了扩容时产生的巨大开销。所以当集合初始化时,最好指定一下容量。
今天先写这么多,后续完了再编辑。
以上是关于数据结构之ArrayList的主要内容,如果未能解决你的问题,请参考以下文章
获取 Intent 片段上的 Serializable ArrayList