文章目录
前言
有些人死了,他还活着,有些人活着,他已经死了。秋天到了,万物复苏。
List是一个接口,List中存的元素是有序可重复的。工作中比较常用的就是ArrayList,本文就聊一下个人对于ArrayList的理解。题外话,为了面试,也要对LinkedList和Vector有所了解 。
ArrayList
ArrayList的底层是Object[],这就不用多BB了吧!每一个看过源码或者背过八股文的人都知道!
1.构造方法
概述:1.无参的构造器会创建一个空的Object[]
2.参数为int的构造器,会创建一个空的Object[]或者长度为参数的Object[]
3.参数为集合的构造器,会创建一个空的Object[]或者将集合转换为Object[]
无参构造方法: //创建一个空的Object[]
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
带参构造方法1://传入一个int类型参数,
如果大于0,则创建该长度的Object[];
如果为0,则创建一个空的Object[];
如果小于0,则抛出异常。
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);
}
}
带参构造方法2://传入一个Collection
将该集合转换为数组;
判断数组长度是否为0,如果不为0,则判断是否为Object数组,如果不是则转换为Object[];
如果数组长度为0,则重新赋值为空的Object[]
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
2.添加元素–>add(E e)
概述:该方法会首先判断是否需要扩容,然后将元素添加的数组中
public boolean add(E e) {
ensureCapacityInternal(size + 1); //判断数组是否需要扩容
elementData[size++] = e;//数组长度+1,并将e放入数组中
return true;
}
3.添加元素–>add(int index, E element)
概述:该方法会首先判断是否数组越界,然后判断需要扩容,然后将元素添加的数组指定下标位置
//判断是否越界,不越界则判断是否扩容,然后移动数据
public void add(int index, E element) {
rangeCheckForAdd(index);//判断是否数组越界
ensureCapacityInternal(size + 1); // 判断数组是否需要扩容
System.arraycopy(elementData, index, elementData, index + 1, size - index);//将index以后的元素向后移动
elementData[index] = element;//将新元素放入数组,下标为index
size++;//数组长度+1
}
4.获取元素–> get(int index)
概述:该方法会首先判断是否数组越界,然后去数组中获取指定下标的元素
public E get(int index) {
rangeCheck(index);//判断是否数组越界
return elementData(index);//返回下标为index的元素
}
5.扩容
概述:扩容机制也很简单,就是创建一下新的数组,数组长度为旧数组的1.5倍
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;//设置旧长度=数组长度;
int newCapacity = oldCapacity + (oldCapacity >> 1);//设置新长度为旧长度+旧长度>>1(可以理解为扩容1.5倍)
if (newCapacity - minCapacity < 0)//minCapacity 为add方法中传来的,新加元素后,需要的数组长度,如果新长度-需要的长度小于0,则新长度重新赋值为minCapacity
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)//如果新长度超过了最大长度,则新长度为最大长度
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);//复制数组元素到新数组里
}
6.indexOf
下雨天打孩子,闲着也是闲着,再看看indexOf方法吧(lastIndexOf同理就不展开了)
public int indexOf(Object o) {//根据元素,获取元素下标
if (o == null) {//判断是否为空
for (int i = 0; i < size; i++)//遍历数组
if (elementData[i]==null)//找到元素值为null的下标并返回该下标
return i;
} else {//元素不是null
for (int i = 0; i < size; i++)//遍历数组,找到相等的元素并返回下标
if (o.equals(elementData[i]))
return i;
}
return -1;//找不到,返回-1
}
//综上,这个方法贼98k简单,算一下时间复杂度是多少呢?O(n)。你真聪明!
总结
ArrayList查询速度比较快,时间复杂度为O(1);
ArrayList增删比较慢,可能需要移动元素,时间复杂度X,O(1)≤X≤O(n)(一般直接说O(n));我相信以你的聪明才智,你肯定知道是怎么计算的。
至此,我们已经看完了ArrayList中常用的方法了。本人水平有限,如果有不对的地方,敬请指正!