一文直接带你吃透 ArrayList
约 833 字大约 3 分钟
Java源码
2020-03-02
ArrayList 是日常开发中相当常见、面试也相当常考的一种 JDK 集合类,了解并熟悉、甚至能实现一个 ArrayList 对面试、提升自己编码功底大有益处。
一、ArrayList 简单使用技巧
/**
* 编写一个ArrayList的简单实用demo
* ArrayList 的常见方法包括:
* add(element):添加元素
* get(index):获取下标元素
* remove(index):移除下标对应元素
* set(index,element):将index处的元素修改为element
*/
public class arrayList {
public static void main(String[] args) {
// 创建 ArrayList 的对象
ArrayList al = new ArrayList();
// 添加元素
al.add("finky");
// 构造随机数并进行添加
Random rnd = new Random();
for (int i = 0; i < 20; i++) {
al.add(rnd.nextInt(1000));
}
// 取出ArrayList里的元素进行打印
for (int i = 0; i < al.size(); i++) {
System.out.print(al.get(i) + " ");
}
// 修改0号index成的元素为doocs
System.out.println();
al.set(0, "doocs");
System.out.println(al.get(0));
// 移除“doocs”元素
al.remove(0);
System.out.println(al.get(0));
}
}
// 这是上面打印后的demo,可以看到第0处下标元素先是修改成了doocs,进行移除后,第0处下标元素变成了912
finky 912 922 284 305 675 565 159 109 73 298 491 920 296 397 358 145 610 190 839 845
doocs
912
二、ArrayList 的源码分析
我们来看看 ArrayList 的源码:
1、来看看 ArrayList 的初始化:
// ArrayList 初始化时默认大小为10
private static final int DEFAULT_CAPACITY = 10;
// 直接初始化的话一个空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
// 初始化ArrayList,传入初始化时的大小
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);
}
}
// 如果不传入大小的话就默认大小是10,那么这里就有一个问题:我们上面插入的元素超过了10,继续插入元素就会进行拷贝扩容,性能不是特别高。所以我们一般情况下初始化时给定一个比较靠谱的数组大小,避免到时候导致元素不断拷贝
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
总结
总结一下 ArrayList 初始化:我们创建 ArrayList 对象时,如果没有传入对应的大小,就会默认创建一个元素大小为 10 的数组,下次插入元素超过 10 时,会进行数组的拷贝扩容,这样性能消耗太高,所以建议就是在初始化时给定一个不要太小的容量大小。
2、 ArrayList 的 add 方法:
先上add
方法的代码:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
private void rangeCheck(int index) {
if (index < 0 || index >= this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
先判断当前数组元素是否满了,如果塞满了就会进行数组扩容,随后进行数组拷贝。
再然后插入元素,同时对应的 index++。