ArrayList:
- 默认初始化容量为10;
- 每次插入前先进行扩容检测及扩容,扩容大小为原容量的一半(例:10+5,扩容后为15);
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
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);
}
CopyOnWriteArrayList:
- 因为它是一个按需分配的数组,所以没有size的概念,它的数组长度便是size,初始容量是一个为0的空数组;
- 它使用 ReentrantLock重入锁来保证多线程安全;
- 疑问:每次都 copy一个新数组,在数据量大的情况下,这会不会有点耗费性能和内存占用?
/** 保护所有冲突变量的锁 */
final transient ReentrantLock lock = new ReentrantLock();
/** 数组只能通过 getArray/setArray访问 */
private transient volatile Object[] array;
/**
* 构造初始化
*/
public CopyOnWriteArrayList() {
setArray(new Object[0]); // 初始化数组
}
/**
* 向数组插入一个对象
*/
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
// 每次都 copy一个新数组,在数据量大的情况下,这会不会有点耗费性能和内存占用?
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
延申:
CopyOnWriteArraySet:
- 直接使用 CopyOnWriteArrayList作为存储结构来实现,插入时比较数组里面所有的值,如果重复则忽略;
- 它也使用 ReentrantLock重入锁来保证多线程安全;
网友评论