1.ArrayLsit和LinkedList区别
答:ArrayList和LinkedList都是List接口的实现类,不同之处在于ArrayList底层使用数组实现,LinkedList底层基于双向链表实现。ArrayList查找快,直接使用数组索引查找,时间复杂度为O(1),但是插入/删除的效率并不高,因为要移动数组插入位置之后的所有元素。而LinkedList查找的时候需要遍历链表,效率低,为O(n),但是LinkedList插入删除的效率高,为O(1)。
2.说说ArrayList在删除/增加元素的时候是怎么修改数组的
答:add()方法是在数组尾部添加元素,当数组长度不够的时候,会调用grow()方法进行扩容处理。删除的时候调用remove()方法,源码如下:
//删除指定索引位置元素
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
//删除指定元素
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
//内部的删除方法
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
(1)在删除指定索引位置的元素的时候,先检查该索引是否合法,不合法会抛出索引越界异常。再把要删除的元素拿出来作为返回值,期间会计算要删除的元素后面还有多少个元素,再调用System.arraycopy(elementData, index+1, elementData, index, numMoved);
移动数组元素,这个方法是一个本地方法,将一个数组从指定位置复制到另外一个数组的指定位置。然后让最后一个元素变成null,将数组大小减一,不置为null会存在引用,无法被GC回收,造成内存泄漏。
(2)删除指定元素和上一个方法类似,主要是这个需要先找到指定元素的索引位置,找不到直接返回false,找到再调用内部的删除方法fastRemove(int index)
来删除,具体操作和上面类似,不再赘述。删除成功后,返回true。
(3)List<Integer> list = new ArrayList<>();
,存有数据1,2,3,4,5,
调用list.remove(5)
会出现什么? 会抛异常
list.remove((Integer) 5)
呢? 会返回true