java集合底层实现复习之List,Vector,LinkedList

List的所有已知实现类:

AbstractList, 
AbstractSequentialList,
ArrayList,
AttributeList,
CopyOnWriteArrayList,
LinkedList,
RoleList,
RoleUnresolvedList,
Stack, 
Vector

其中最为常用的实现是:ArrayList,Vector ,LinkedList

ArrayList

底层实现:是通过数组来实现的,如下:源码:(以下源码为jdk1.8)

    transient Object[] elementData; 

默认创建的是为空的默认数组:

 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
.......
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

当添加一个新的元素时的流程:

进入add方法
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;
..............
private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
	 这里先进入的是以下 的函数,在函数的参数里面调用的是上面的,以此来判   	
	 断是否其是否为空的默认数组,然后返回默认的长度:
private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
这里如果容量大于数组的长度就调用grow方法进行扩容,
如果没大于其数组的长度直接返回到add方法中并且直接将数据放入到数组中:
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
扩容中是原来数组的1.5倍:newCapacity = oldCapacity + (oldCapacity >> 1);
如果**新的容量还是小于需要的容量则新的容量为需要的容量** 
 这里就是将第一次add的时候默认的将数组的容量变为10
 如果大于MAX_ARRAY_SIZE :
 	 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 则将数组的的长度赋值为hugeCapacity(minCapacity) 这里判断了是否大于 MAX_ARRAY_SIZE,
 如果大于则数组的最大长度为int的最大值
 否则为MAX_ARRAY_SIZE 
    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);
    }
private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
经过以上的步骤完成了并且将数据放入数组的位置:
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
 例如:
当新建的一个ArrayList其容量为0,
调用add方法时,先进入ensureCapacityInternal()方法确保其内部的容量
在ensureCapacityInternal中调用了一个calculateCapacity来判断数组的长度是否为默认的空数组
 如果为空数组的话则返回最大的值为其默认的容量minCapacity 为10,然后因为其大于数组的长度所以
 进入扩容grow方法:在grow方法中调用,在grow中因为其newCapacity为0小于minCapacity,
 10必定小于MAX_ARRAY_SIZE,因此直接数组复制到新的数组中

特点ArrayList是List使用中最常用的实现类,它的查询速度快,效率高,但增删慢,线程不安全。删除和在中间新增的话主要是因为其数组内部的元素的移动

Vector

底层的实现:也是通过数组来实现的:
 protected Object[] elementData;
初始的数组的容量如果不指定的话,就是10,如果指定的话就是自己指定的大小

----未指定容器的大小
   public Vector() {
        this(10);
    }
------指定容器大小

public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }
 
 ---指定容器大小,容器的增加向量
public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }
---capacityIncrement是为了后面扩容的时候,capacityIncrement 大于0的话
	增加的是 原来的长度+capacityIncrement,
	如果等于0和小于0的话是2倍原来的长度
add方法中:ensureCapacityHelper:
	方法是为了确保其的容量不超过数组的大小
    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);
    }
Vector 的扩容的方法:grow:中和ArrayList差不多,
	就是在普通扩容的是判断增长量是否大于0 如果大于0增长的是 
		原来的长度+指定的增长长度
		如果小于的话是:
			原来的长度+原来的长度 即(2倍的原来的长度)
    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);
    }

特点:其特性和ArrayList差不多,主要是其实线程安全的,该集合的方法中添加了synchronized 所以是线程安全的

LinkedList

	LinkedList的底层的实现是一个双向链表Node
 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;
        }
    }
其添加机制:add方法主要是通过调用:linkLast和linkFrist来实现:
 public boolean add(E e) {
        linkLast(e);
        return true;
    }
linkFirst的实现:主要是往头结点的增加节点
    private void linkFirst(E e) {
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }
linkLast的实现:主要是往链表的后面的添加节点
    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++;
    }

特点:查询慢,但是删除和增加的效率比较高。线程是不安全的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值