Collection - List集合

目录

知识体系结构

Vector

Stack

ArrayList

LinkedList

CopyOnWriteArrayList

总结


知识体系结构

Vector

Vector类是一个可增长的对象数组,是线程安全的。

我们看下它的图解关系图:

 蓝色实线:extends,继承一个类,可以使用所有父类的方法

 绿色虚线:implements,实现一个类,重写父类的方法

继承与实现的类都有什么作用:

AbstractList、List:继承AbstractList,实现List,提供了基本的添加,删除,修改,遍历等操作,是最基本的骨架

Cloneable:实现了Cloneable,即可以使用clone方法

RandomeAccess:具有随机性

Vector类中变量

//存放元素的数组
protected Object[] elementData;
//数组大小
protected int elementCount;
//扩容增加大小
protected int capacityIncrement;

 构造方法:

/**
 * initialCapacity: 初始容量
 * capacityIncrement: 扩容大小
 * Collection:集合
 */
public Vector(int initialCapacity,int capacityIncrement)

public Vector(int initialCapacity)

//Vector默认初始容量为10
public Vector(){this(10)}

public Vector(Collection<? extends E> c)

Vector添加元素与扩容机制:

    /**
     * Appends the specified element to the end of this Vector.
     *
     * @param e element to be appended to this Vector
     * @return {@code true} (as specified by {@link Collection#add})
     * @since 1.2
     */
    public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }
    
    private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    
    /**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

Vector将元素添加到数组末尾,每次添加元素都会判断是否超过数组容量,如果大于等于数组容量,会判断扩容大小是否大于0,如果大于0,则旧容量加上定义的增量因子为新容量,如果没有定义增量因子(默认0)则新容量是旧容量的两倍。

Stack

Stack(栈)是线程安全,先进后出的集合,是Vector的子类,目前已不推荐使用

 内部实现只有一个无参构造和五个方法:

push:将与元素压入栈中,相当于在数组后面追加一个元素

pop:取出数组末尾的元素,并删除

peek:取出数组的末尾的元素,不删除

empty:判断该栈是否为空

search:搜索元素在数组中的位置

ArrayList

ArrayList是数组实现的,线程不安全的,比较高效的集合,是目前比较常用的List

继承与实现类和Vector相同,那使用的方法也差不多一样,这里与Vector做一下比较:

相同:1、继承与实现类都是一样的

           2、底层都是数组实现的,默认初始容量大小都是10

不同:1、扩容方式不同:Vector新容量可以自定义扩容增量大小,没有自定义扩容增量大小,默认是0,新容量是旧容量的两倍,而ArrayList新容量是旧容量的1.5倍(新容量=旧容量*1.5)

            2、Vector是线程安全的,方法上有synchronized关键字修饰,ArrayList是线程不安全的

直接看ArrayList添加元素与扩容机制:

    /**
     * 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) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    
    /**
     * 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);
    }

ArrayList每次添加元素都会判断容量是否大于等于当前容量,扩容时新容量是旧容量的两倍,按ArrayList默认初始容量来计算就是10 +(10/2)= 15,扩容时运用的位运算参考下图

LinkedList

LinkeList是基于双向链表实现,线程不安全,比较高效的集合,是目前比较常用的集合

类关系图:

LinkedList相比与Vector与ArrayList少了RandomAccess类,即不支持随机性,只能从头到尾遍历找出所在的元素

LinkedList的添加元素:

     /**
     * Appends the specified element to the end of this list.
     *
     * <p>This method is equivalent to {@link #addLast}.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    
    /**
     * Links e as last element.
     */
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }

    private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

LinkedList默认时间元素添加到列表末尾,可以添加到表头,末尾,和指定位置

add 流程图如下所示

CopyOnWriteArrayList

copyonwriteArrayList是数组实现的线程安全的集合

 CopyOnWriteArrayList添加元素与扩容机制:

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    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();
        }
    }

copyOnWriteArrayList每添加一个元素,都会将数组的元素复制到新数组中去,新数组大小加1,再将新元素添加到新数组,适合读多写少的场景。

总结

List集合名称底层结构  线程安全扩容机制优 / 缺 点
Vector数组线程安全(synchronized)首先判断容量大小是否占满,如果有自定义的扩容容量大小,则每次扩容新容量是旧容量加上扩容容量大小,否则新容量是旧容量的两倍

优点:可根据index快速找到对应的元素,支持随机性

缺点:增删慢,每次扩容都会将老数组元素复制到新数组(考虑数据量比较大的情况)

Stack数组线程安全(synchronized)是Vector的子类,使用的是Vector的扩容机制
ArrayList数组线程不安全首先判断容量大小是否占满,新容量是旧容量的1.5倍
CopyOnWriteArrayList数组线程安全(ReentrantLock)每次添加元素都会将数组元素复制的到新数组,新数组大小加1,再将元素添加进行新数组
LinkedList双向链表线程不安全优点:增删快,遍历慢,每次都要从头部开始遍历查找,不支持随机性

后续会跟踪记录Synchronized和ReentrantLock的源码和区别
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值