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 Nodetransient Node
与 ArrayList 的比较
上一篇:6-二维数组中的查找
下一篇:python实现两个升序链表合并
文章标题:Java面试3——Java8List源码解析
文章链接:http://soscw.com/index.php/essay/58095.html