一:ArrayList
ArrayList
底层采用数组。其元素的增、删、改、查采用Arrays.copyOf()
实现。
- 初始化时默认
ArrayList
容量为10
,但不申请内存。只有在add、addAll
时才真正的去申请内存。
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 增加容量,确保至少能保存 minCapacity 个元素
* @param minCapacity the desired minimum capacity 预期最小容量
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
// 增加50%的容量
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); // 新增 newCapacity 个容量
}
-
当初始化
ArrayList
时最好先指定ArrayList
的大小。这样可以减少每次数组扩展的频率,提高效率。 -
ArrayList
不支持并发,如果想在并发中使用ArrayList
需要向下面这样。
List list = Collections.synchronizedList(new ArrayList(...))
- 觉得
ArrayList
有意思的batchRemove
源码
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
// 双角标操作数组元素
for (; r < size; r++)
// 如果角标 r 位置的元素在 c 中存在。(根据参数来判断)
if (c.contains(elementData[r]) == complement)
// 将数组 elementData 角标 r 位置上的元素,放到数组 elementData 角标为 w 的位置上。w 为实际 c 中存在元素的个数(根据参数来判断)
elementData[w++] = elementData[r];
} finally {
// 如果抛出异常时,才走这里。否则 r 永远都等于 size
if (r != size) {
// 如果抛出异常,只保留 r 位置之后的元素
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
// 如果 w 等于 size,说明 elementData 中的所有元素都是需要移除或者保留的
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
// 只保留 w 位置之前的元素
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
二:LinkedList
LinkedList
底层采用双链表。其元素的增、删、改、查采用链表的指针实现。
- 链表节点适合快速插入。其它的没啥好说的....源码很简单
总结
-
ArrayList
比LinkedList
更适合get
元素,add
时LinkedList
分状态两者差不多。 - 占用空间上
ArrayList
要更小一些 - 有兴趣可以看看这个
网友评论