在Java编程语言中,ArrayList是一个非常常用的集合类,它基于动态数组实现,提供了高效的随机访问能力。本文将深入浅出地解析Java ArrayList的源码,并分享一些实战技巧。
ArrayList的基本原理
ArrayList是Java集合框架中的一个可调整大小的数组实现。它继承自AbstractList类,并实现了List、RandomAccess、Cloneable和Serializable接口。ArrayList在内部使用一个动态数组来存储元素,数组的大小是ArrayList的一个重要属性。
动态数组的工作原理
- 初始化:ArrayList在创建时,默认会初始化一个长度为10的数组。
- 扩容:当向ArrayList中添加元素时,如果数组已满,ArrayList会自动进行扩容,扩容后的长度通常是原长度的1.5倍。
- 内存浪费:由于ArrayList的扩容是基于1.5倍的增长,因此有时会出现内存浪费的情况。
ArrayList源码解析
构造方法
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ARRAY;
} else {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
构造方法中,会根据传入的初始容量创建数组,如果传入的容量小于0,则会抛出异常。
主要方法
添加元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!! // 确保数组有足够的空间
elementData[size++] = e; // 将元素添加到数组的最后一个位置
return true;
}
add方法首先会调用ensureCapacityInternal方法确保数组有足够的空间,然后将元素添加到数组的最后一个位置。
扩容方法
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ARRAY) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
if (minCapacity - elementData.length > 0) {
grow(minCapacity);
}
}
ensureCapacityInternal方法会根据传入的最小容量来确保数组有足够的空间,如果空间不足,则调用grow方法进行扩容。
获取元素
public E get(int index) {
rangeCheck(index); // 检查索引是否在范围内
return elementData(index);
}
get方法用于获取指定索引的元素,首先会检查索引是否在范围内,然后从数组中获取对应的元素。
实战技巧
使用泛型
使用泛型可以避免运行时出现ClassCastException,例如:
ArrayList<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");
注意扩容
由于ArrayList的扩容是基于1.5倍的增长,因此在进行大量添加操作时,最好提前预估容量,避免频繁扩容。
使用迭代器
使用迭代器可以安全地遍历ArrayList,避免在遍历过程中修改集合:
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
总结
本文深入浅出地解析了Java ArrayList的源码,并分享了一些实战技巧。希望读者通过本文能够更好地理解ArrayList的工作原理,并在实际开发中灵活运用。
