1 参考文档
- http://www.matools.com/api/java8 中文API文档
- 源码
- https://www.cnblogs.com/zhangyinhua/p/7687377.html#_labelTop 写得很清楚的大牛博客一篇
2 ArrayList类简介
简单说,它是一个可调整大小的数组,容量自动增长,并允许所有元素存在,包括null。
非线程安全,但是可以使用Collections中的同步方法进行包装。这样就是线程安全的了。
(与其对应的就是Vector类了,本身线程安全)
List list = Collections.synchronizedList(new ArrayList(...));
3 了解它的类继承关系和实现接口
(IDEA的类图自动生成挺好用的)
4 看源码啦
4.1 成员变量
private static final long serialVersionUID = 8683452581122892189L;
/**
* Default initial capacity.
*/
// 默认的容量
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
*/
//空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
//默认的空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
//底层的数组,存放数据
transient Object[] elementData; // non-private to simplify nested class access
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial
*/
private int size;
4.2 初始容量及自动扩容
默认的初始容量是10,扩容为原来大小的1.5倍
上面的默认构造函数,可以看见,elementData(object[] )的属性被赋值DEFAULTCAPACITY_EMPTY_ELEMENTDATA( object[] )
下面的构造函数可以自己制定数组的大小,不过该数字有最大限制,该类中定义了一个限定数组长度的变量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
测试了下,这个值是2147483639,emm,很大了
System.out.println(Integer.MAX_VALUE-8);
//2147483639
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
// 初始化elementData数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
4.3 常用的函数
Add
添加一个新值,成功返回true,失败返回false
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++;
}
ensureCapacityInternal(int minCapacity)
private void ensureCapacityInternal(int minCapacity) {
// 如果elementData 为空,
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 将容量设置为默认容量
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
// emm 明确确认是否够用
ensureExplicitCapacity(minCapacity);
}
ensureExplicitCapacity(int minCapacity)
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
// 需要扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
grow(int minCapacity)
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//1.5倍扩容
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// 扩容操作
elementData = Arrays.copyOf(elementData, newCapacity);
}
hugeCapacity(int minCapacity)
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
// 如果容量大于MAX_ARRAY_SIZE ,那newCapacity = Integer.MAX_VALUE
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
整个过程的函数调用如图:
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;
}
set
将数组中指定位置的元素替换为指定的元素。成功返回旧值
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
get
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
5 总结
1)arrayList可以存放null。
2)arrayList本质上就是一个elementData数组。
3)arrayList区别于数组的地方在于能够自动扩展大小,其中关键的方法就是grow()方法。
4)arrayList中removeAll(collection c)和clear()的区别就是removeAll可以删除批量指定的元素,而clear是全是删除集合中的元素。
5)arrayList由于本质是数组,所以它在数据的查询方面会很快,而在插入删除这些方面,性能下降很多,有移动很多数据才能达到应有的效果
6)arrayList实现了RandomAccess,所以在遍历它的时候推荐使用for循环。