今天,主要看了下List接口及其实现类,整体的类结构图如下。
主要的几个实现类为ArrayList, LinkedList, Vector,下面分别进行介绍。
1. ArrayList
1.1 数据结构
数组
1.2 扩容机制
先扩容再插值
当添加元素时,执行ensureCapacityInternal(int minCapacity)
方法执行扩容逻辑,具体源码如下:
/**
* 在列表末尾追加元素
*/
public boolean add(E e) {
// 执行扩容逻辑
ensureCapacityInternal(size + 1); // Increments modCount!!
// 添加元素
elementData[size++] = e;
return true;
}
/**
* 在索引位index上插入元素,后面元素随之后移一位
*/
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++;
}
实际扩容逻辑grow(int minCapacity)
:
/**
* 扩容
* 如果旧容量*1.5<minCapacity,以minCapacity容量为准;否则,设置1.5*旧容量
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
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);
}
ArrayList对外提供了ensureCapacity,可以由用户显式调用,当发生大量元素添加时,可以一次性分配足量的空间,避免数组多次扩容开销。
1.3 源码
/**
* 可变数组实现
* 除了非线程安全,与Vector类似
* O(1)方法 size/isEmpty/get/set/iterator/listIterator
* ≈O(1)方法 add
* ensureCapacity可以在批量添加大量元素前,对数组容量进行扩容,可以减少重复扩容的次数
* @see Collection
* @see List
* @see LinkedList
* @see Vector
* @since 1.2
*/
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
/**
* 默认初始化数组容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 公用的空数组实例
*/
private static final Object[] EMPTY_ELEMENTDATA = {
};
/**
* 公用的默认容量空实例,第一个元素添加时,自动扩容到默认大小10
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
};
/**
* 底层的数组存储buffer
*/
transient Object[] elementData; // non-private to simplify nested class access
private int size;
/**
* 构造一个指定容量的数组列表
*/
public ArrayList(int initialCapacity)
/**
* 构造一个空的默认容量列表
*/
public ArrayList()
/**
* 构建包含给定集合c中所有元素的列表,列表元素保持了集合迭代顺序
*/
public ArrayList(Collection<? extends E> c)
/**
* 将列表容量与当前实际元素个数设置一致,可以最小化存储空间
*/
public void trimToSize()
/**
* 扩容,在批量添加元素时先显式调用该方法可以减少系统重复扩容分配空间的开销
*/
public void ensureCapacity(int minCapacity)
private void ensureCapacityInternal(int minCapacity)
private void ensureExplicitCapacity(int minCapacity)
/**
* 数组的最大容量
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* 扩容
* 如果旧容量*1.5<minCapacity,以minCapacity容量为准;否则,设置1.5*旧容量
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
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);
}
public int size()
public boolean isEmpty()
public boolean contains(Object o)
/**
* 返回元素第一次出现的索引
* 不存在,返回-1
*/
public int indexOf(Object o)
/**
* 返回元素最后一次出现的索引
* 不存在,返回-1
*/
public int lastIndexOf(Object o)
public Object clone()
public Object[] toArray()
public <T> T[] toArray(T[] a)
// Positional Access Operations
E elementData(int index)
/**
* 返回列表指定索引位置的元素
*/
public E get(int index)
/**
* 用给定的元素替代列表某个索引位上的元素
*/
public E set(int index