java中集合常用实现类区别及源码分析之List集合

java中集合的使用无处不在,本次对于list集合常用实现类介绍

1.List

list在java开发是的的频率非常高比如使用mybatis或者hibernate查询数据返回的实体集合常用list接收,list是一个java接口,我们常用ArrayList、linkedlist、vector等实现类来创建List对象
a)ArrayList
1.ArrayList底层数据存储基于数组
2.底层数组默认大小为10,当超过新加一个元素的数据大小超过数组大小时,创建一个新数组,新数组大小=1.5*老数组
3.多线程不安全
4.随机访问速度较快,可以直接通过数组下标返回数据

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
    /*** 默认初始化大小*/
    private static final int DEFAULT_CAPACITY = 10;
    /*** 空数组时的数据*/
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**默认创建时例时空数据的值*/
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**集合和数据存储的元素数据,这就是ArrayList底层基于数组的原因*/
    transient Object[] elementData; // non-private to simplify nested class access

    /**数据的大小**/
    private int size;
     /**
     * 无参构造方法、赋予数组默认为一个空数组
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
      /**
     * 构造方法指定底层数组默认大小
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
    /**
     * 集合最常用方法、添加元素、
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    //传入参数为当前size+1
     private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    //判断当时集合内数据是否为默认空数据,若为true则返回当前size+1与默认值10中大的一个数据
    //这就是为什么初始化赋予的值未空数组,但是默认初始化大小为10,就是当调用add方法时赋予的size
	private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
	//判断数据是否应该扩容
	private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    //扩容至1.5倍
    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);
    }

b)、linkedList
1.数据插入、删除较快
2.数据遍历速度快
3.不能随机访问
4.多线程不安全

public class LinkedList<E> extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
	//大小
	transient int size = 0;

    /**
     * 标记第一个值
     * 恒定不变的: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first;

    /**
     * 标记最后一个值
     * 恒定不变: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last;
	/**
     * 追加元素到最后一个节点 **/
    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    //添加到最后一个元素
     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++;
    }

3.Vector
1.不指定一块内存大小的数组的连续存储,即可以像数组一样操作,但可以对此数组进行动态操作。通常体现在push_back() pop_back()
2.随机访问方便,即支持[ ]操作符和vector.at()
3. 节省空间。
4. 在内部进行插入删除操作效率低。
5. 只能在vector的最后进行push和pop,不能在vector的头进行push和pop。
6. 当动态添加的数据超过vector默认分配的大小时要进行整体的重新分配、拷贝与释放
7. 多线程安全

4.CopyOnWriteArrayList
1、适合使用在读操作远远大于写操作的场景里,比如缓存。发生修改时候做copy,新老版本分离,保证读的高性能,适用于以读为主的情况。
2、多线程安全,轻量级锁实现多线程安全。
3、采用“写入时复制”策略,对容器的写操作将导致的容器中基本数组的复制,性能开销较大。所以在有写操作的情况下,CopyOnWriteArrayList性能不佳,而且如果容器容量较大的话容易造成溢出

猜你喜欢

转载自blog.csdn.net/qq_38318330/article/details/107922882