Java面试3——Java8List源码解析
2021-02-20 18:19
标签:size element nal syn obj get warnings 实现 row 关注【星辰学院】 http://xingchenxueyuan.com 更多知识和内容,一起打怪升级! ArrayList 是基于数组实现的,支持快速随机访问。 数组的默认大小为 10。 存储结构如图: 添加元素时使用 ensureCapacityInternal() 方法来保证容量足够,如果不够时,需要使用 grow() 方法进行扩容,新容量的大小为 扩容操作需要调用 写操作在一个复制的数组上进行,读操作还是在原始数组中进行,读写分离,互不影响。 写操作需要加锁,防止并发写入时导致写入数据丢失。 写操作结束之后需要把原始数组指向新的复制数组。 CopyOnWriteArrayList 在写操作的同时允许读操作,大大提高了读操作的性能,因此很适合读多写少的应用场景。 但是 CopyOnWriteArrayList 有其缺陷: 所以 CopyOnWriteArrayList 不适合内存敏感以及对实时性要求很高的场景。 基于双向链表实现,使用 Node 存储链表节点信息。 每个链表存储了 first 和 last 指针: 结构图 ArrayList 基于动态数组实现,LinkedList 基于双向链表实现。ArrayList 和 LinkedList 的区别可以归结为数组和链表的区别: 关注【星辰学院】 http://xingchenxueyuan.com 更多知识和内容,一起打怪升级! Java面试3——Java8List源码解析 标签:size element nal syn obj get warnings 实现 row 原文地址:https://www.cnblogs.com/fisherwangcn/p/12681225.html
ArrayList
概览
扩容
oldCapacity + (oldCapacity >> 1)
,也就是旧容量的 1.5 倍。Arrays.copyOf()
把原数组整个复制到新数组中,这个操作代价很高,因此最好在创建 ArrayList 对象时就指定大概的容量大小,减少扩容操作的次数。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);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
删除元素
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;
}
* @param src the source array. 源数组
* @param srcPos starting position in the source array. 源数组的起始位置
* @param dest the destination array. 目标数组
* @param destPos starting position in the destination data. 目标数组的起始位置
* @param length the number of array elements to be copied. 复制的长度
public static native void arraycopy(Object src,int srcPos,Object dest, int destPos,int length)
Vector
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
CopyOnWirteArrayList
读写分离
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
final void setArray(Object[] a) {
array = a;
}
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
2. 适用场景
LinkedList
概览
private static class Node
transient Node
与 ArrayList 的比较
上一篇:6-二维数组中的查找
下一篇:python实现两个升序链表合并
文章标题:Java面试3——Java8List源码解析
文章链接:http://soscw.com/index.php/essay/58095.html