面试——ArrayList
1. 底层研究
1. ArrayList
底层是数组
1. 无参构造
构造一个初始容量为10的空列表
当给空数组链表添加第一个数据的时候,数组链表才会初始化长度
2. 有初始化容量的构造
3. 扩容
2. LinkedList
底层是链表
2. 有用过ArrayList吗?它是做什么用的?
- ArrayList就是数组列表,底层是数组
- ArrayList在装载基本数据类型时,实际装载的是对应的包装类
- 与ArrayList类似的还有LinkedList,他们俩相比:
- ArrayList:查找和访问元素的速度快,新增、删除的速度慢。线程不安全,使用频率高。查询时间复杂度O(1)
- LinkedList:查找和访问元素的速度慢,新增、删除的速度快。查询时间复杂度O(n)
3. ArrayList线程不安全,为什么还要去用?
Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。
实际开发中有以下几种场景:
- 频繁增删:使用LinkedList,但是涉及到频繁增删的场景不多
- 追求线程安全:使用Vector
- 普通的用来查询:使用ArrayList,使用的场景最多
根据数据结构的特性,三者难以全包含,只能在相互之间做取舍
4. ArrayList底层是数组,那是怎么实现不断扩容的?
- 使用ArrayList空参的构造器创建集合时,数组并没有创建。当集合中添加第一个元素时,数组被创建,初始化容量为10
- 当数组长度+1>数组容量时,这时需要对数组进行扩容,扩容公式:新长度=原长度+原长度>>1,也就是扩容到了原来的1.5倍
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;