1. 底层不同
- ArrayList基于动态数组
- LinkedList基于双向链表
2. 查询、插入、删除的效率不同
- 对于随机访问get,设定值set方法,ArrayList的效率高于LinkedList,因为动态数组可以随机访问的,适用于查询很多的场景。而LinkedList需要通过移动指针一步一步到节点处,比较费时。
- 对于插入、删除方法,LinkedList的效率要优于ArrayList,为啥呢,LinkedList只需要移动指针指向需要的节点对象即可以,而ArrayList需要移动数据来填补被删除的对象的空间
3. 使用场景不同
-
当经常需要执行查询操作时,适合使用ArrayListList
-
当我们不知道数据量的大小时或者经常执行插入删除的操作,适合使用LinkedList
4. ArrayList需要扩容的问题
当ArrayList的空间不够用时,会自动申请内存,叫做扩容。
/**
* minCapacity:当前需要的容量是minCapacity,扩容后的容量应当大于等于minCapacity
*/
private void grow(int minCapacity) {
int oldCapacity = elementData.length; // 扩容前的容量
int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量等于扩容前容量的1.5倍
// 如果新容量还不够用,那么就扩容到minCapacity得了
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果新容量超过ArrayList最大容量,那么就用最大容量了(ArrayList的容量总得有个上限吧)
// 插一句:最大容量为:0x7fffffff-8
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 扩容的核心就是这句话,将旧数组里的内容复制到新数组里
// 这个操作很耗时,因此我们应当尽量减少扩容
elementData = Arrays.copyOf(elementData, newCapacity);
}
在这里可以很清楚的看到扩容容量的计算:
int newCapacity = oldCapacity + (oldCapacity >> 1)
调用无参构造函数默认初始容量为10
其中oldCapacity是原来的容量大小,oldCapacity >> 1 为位运算的右移操作,右移一位相当于除以2,所以这句代码就等于int newCapacity = oldCapacity + oldCapacity / 2;即容量扩大为原来的1.5倍(注意我这里使用的是jdk1.8,没记错的话1.7也是一样的),获取newCapacity后再对newCapacity的大小进行判断,如果仍然小于minCapacity,则直接让newCapacity 等于minCapacity,而不再计算1.5倍的扩容。然后还要再进行一步判断,即判断当前新容量是否超过最大的容量 if (newCapacity - MAX_ARRAY_SIZE > 0),如果超过,则调用hugeCapacity方法,传进去的是minCapacity,即新增元素后需要的最小容量:
转载:https://blog.csdn.net/u010429424/article/details/76220058