1、ArrayList 概述
ArrayList 是 Collection 单例集合体系中使用率最多的一个集合。是 List 的第一个实现类,全面替代了 Vector 。底层是数组结构的.
特点:
有序、有索引、可以重复。
基本使用:
ArrayList<Integer> al = new ArrayList<>();
al.add(1);
al.add(2);
al.add(3);
2、ArrayList 的四种遍历方式:
2.1、增强for
//i只是其中的一个变量,更改i的值,不会更改集合中的数据
for (Integer i : al) {
System.out.println(i);
}
2.2、迭代器
//在迭代的时候不能利用集合的方法改变集合的长度。会报并发修改异常
Iterator<Integer> it = al.iterator();
while(it.hasNext()){
Integer next = it.next();
System.out.println(next);
}
2.3、普通for
//在删除数据的时候,要i--。否则会导致相邻的两个数不能删除
for (int i = 0; i < al.size(); i++) {
Integer ii = al.get(i);
System.out.println(ii);
}
2.4、转数组
Object[] array = al.toArray(); //toArray()没有传递参数,所以是object类型的
for (Object o : array) {
System.out.println(o);
}
Integer[] array = al.toArray(new Integer[0]);//传递一个T类型的数组,那么返回值就是T类型的。
//此处数组长度与集合长度比,谁长听谁的,不足null补齐。
//所以可以写0或者是集合的size
for (Integer i : array) {
System.out.println(i);
}
3、方法解析:
3.1、无参构造
ArrayList<Integer> al = new ArrayList<>();
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
//elementData 是ArrayList底层实际存值的数组
//EMPTY_ELEMENTDATA 是一个object类型的空数组
//创建对象的时候ArrayList就是一个空数组
}
3.2、add():
void add(int index, E element):将指定的元素插入此列表中的指定位置。
//如果集合中最大索引是3,那么调用此方法,可以在4索引插入元素。但是超过4索引就报错了。
boolean add(Object e): 向集合中添加元素。
//方法源码分析:
public boolean add(E e) {
ensureCapacityInternal(size + 1);//重新计算长度,并让modCount++
//modCount是并发修改异常中的关键,下面会解释
elementData[size++] = e;//每次往数组的末尾存。保证了存取有序
return true; //因为ArrayList可重复所以每次都是true。跟HashSet相对
}
//-----------------------
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//默认大小跟实际大小比较
}//保证了ArrayList只要刚开始添加就有一个默认10大小的容量,因为DEFAULT_CAPACITY = 10;
ensureExplicitCapacity(minCapacity);
}
//------------------------
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//modCount是并发修改异常中的关键,下面会解释
if (minCapacity - elementData.length > 0)//比较长度
grow(minCapacity);
}
//------------------------
private void grow(int minCapacity) {
int oldCapacity = elementData.length;//旧容量
int newCapacity = oldCapacity + (oldCapacity >> 1);//新容量 = 旧容量 + 旧容量/2
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);//数组的拷贝//底层调用System.arraycopy拷贝
}
综上所述:ArrayList 底层是一个长度为0的数组。在刚添加一个元素后,变成默认大小10。
只要是存满了。那么就把原来的长度*1.5(也就是扩容原先的1.5倍大小。)
再创建了一个新的数组,新的数组的长度为原来的1.5倍
利用 System.arraycopy 的方法将原数组的内容拷贝到新的数组中去。
3.3、clear():
void clear():清空集合中所有元素。
//方法源码分析
for (int i = 0; i < size; i++) //遍历集合
elementData[i] = null; //得到每一个元素,把每一个元素变成null
size = 0; //将长度变为0
3.4、contain():
boolean contains(Object o):判断集合中是否包含某个元素。
//方法源码分析
public boolean contains(Object o) {
return indexOf(o) >= 0;//调用indexOf看参数在集合中是多少索引。
//如果索引为正数,那么集合中就包含参数
}
//------------------------
public int indexOf(Object o) {
if (o == null) { //判断参数是否为null
for (int i = 0; i < size; i++)//遍历
if (elementData[i]==null)//判断遍历到的是否为null
return i; //如果存在就直接return
} else {
for (int i = 0; i < size; i++) //遍历
if (o.equals(elementData[i])) //利用equals进行判断
return i; //如果存在就直接return
}
return -1;//如果不存在就return-1
}
综上所述:"方法底层是依赖 equals" 方法来判断是否是否与集合内部某一个元素相同。
如果我们没有重写equals。那么用的是object里面的equals。此时判断的是地址值。
当遇到一个匹配的直接return,所以当重复时候,只能返回第一个。
3.5、isEmpty():
boolean isEmpty():判断集合中的元素是否为空
//方法源码分析
public boolean isEmpty() {
return size == 0;//就是判断长度是否为0
}
3.6、remove(Object o):
boolean remove(Object o):根据元素的内容来删除某个元素
后续。。。。