ArrayList 类
优点:尾插效率高,支持随机访问
缺点:中间插入或者删除效率低。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
//初始容量10
private static final int DEFAULT_CAPACITY = 10;
//数组结构
transient Object[] elementData;
}
add方法有两个,默认在数组末尾插入,固定返回boolean比较简单;下面的值在指定位置插入
public void add(int index, E element) {
//验证位置是否越界
rangeCheckForAdd(index);
//扩容,默认长度的一半,存在特殊情况
//特殊情况1,扩容为当前size+1
//特殊情况2,扩容为 Integer.MAX_VALUE或者MAX_ARRAY_SIZE;
ensureCapacityInternal(size + 1);
//浅copy去改变下标,指定位置后面的数据全部右移一位
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//空出的位置给添加的对象
elementData[index] = element;
//长度+1
size++;
}
简单介绍下System.arraycopy,用的挺多的,效率比循环快
* src表示源数组
* srcPos表示源数组中拷贝元素的起始位置。
* dest表示目标数组
* destPos表示拷贝到目标数组的起始位置
* length表示拷贝元素的个数
*/
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
remove方法也有两个,
public E remove(int index) {
//检查下标是否越界
rangeCheck(index);
//数组操作的次数,主要迭代时使用,如果迭代时发现次数改变,则异常
modCount++;
//取出删除的值,返回使用
E oldValue = elementData(index);
//改变的元素个数, 例如index=2,集合存的0~9十个元素,size=10,则0,1后面七个元素被改变,10-2-1=7
int numMoved = size - index - 1;
if (numMoved > 0)
//指定位置后面的数据全部左移一位
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//最后一位制为null,让GC去删除
elementData[--size] = null; // clear to let GC do its work
//返回删除的值
return oldValue;
}
public boolean remove(Object o) {
if (o == null) {
//循环找到对应的值的下标,然后删除,删除操作与上面remove相似。只删除一个。
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;
}
有个小疑问,为什么上面的remove方法不写成下面的样子,清楚地同学可以留言说一下。
public boolean remove(Object o) {
for (int index = 0; index < size; index++)
if (elementData[index] == null || o.equals(elementData[index])) {
fastRemove(index);
return true;
}
return false;
}
没啥说的,根据下标查出来
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
虽然是set,但是更新操作,不是新增操作。
public E set(int index, E element) {
rangeCheck(index);
//取出旧值,返回用
E oldValue = elementData(index);
//更新指定下标对应的值
elementData[index] = element;
return oldValue;
}
ArrayList的大小如何自动增加的
看上面的add方法就是答案,简单说每次add都会扩容,默认增加size的一半。
什么情况你会使用ArrayList
一般听到这个问题就有点苦恼,这不是基本操作吗,还用问???
可以简单说,数据库读取数据时使用,因为有序且不需要删除操作,效率高。
在索引中ArrayList的增加或者删除某个对象的运行过程,效率很低吗,为什么?
效率肯定低了,因为arrayCopy 操作耗费内存。
ArrayList如何顺序删除节点
迭代器是顺序删除的,for循环也可以,不过要从list的尾部开始删除,因为从头部删除,头部会被后面数据覆盖,头部下标依然有数据。
ArrayList的遍历方法
迭代器 hasNext方法,for循环遍历,foreach和上题一样