您的位置:首页 > 编程语言 > Java开发

【java基础】List

2016-02-24 15:27 495 查看
1.概括

1. ArrayList是实现List接口的动态数组,动态就是大小可变。是线程不安全的,适用于查找速度快,对插入删除慢的场景。创建时默认初始容量为10。随着ArrayList中元素的增加,它的容量也会不断的自动增长。每次添加元素时都会判断是否需要扩容,扩容后会进行数组的重新拷贝

2. LinkedList是基于链表的实现方式,同样实现List接口,是线程不安全的。适用于查找速度慢,对插入删除要求快的场景。LinkedList在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。

3. Vector可以实现可增长的对象数组,实现List接口。与数组一样,它包含可以使用整数索引进行访问的组件。不过,Vector的大小是可以增加或者减小的,以便适应创建Vector后进行添加或者删除操作。实现了List接口,是线程安全的。跟ArrayList一样,添加元素也是要判断是否需要扩容并进行数组的重新拷贝。

4. Stack是先进后出的对象堆栈,继承自Vector,并通过empty(),peek(),pop(),push(E item),search(Object o)进行扩展。

2.效率

1. ArrayList

public void add(int index, E element) {  
    rangeCheckForAdd(index);   
    ensureCapacityInternal(size + 1);  //扩容操作  
    System.arraycopy(elementData, index, elementData, index + 1, size - index);//数组拷贝  
    elementData[index] = element;   //插入  
    size++;  
    }


arraycopy(Object src, int srcPos, Object dest, int destPos, int length);


arraycopy这个方法将源数组src的第srcPos位置开始的length个元素移动到目标数组dest的第destPos个位置开始的length个位置。是非常耗时和效率低的操作。故ArrayList不适合插入频繁的场景。

2.LinkedList

增加元素时index等于size则插在末尾,否则调用linkBefore

public void add(int index, E element) {  
        checkPositionIndex(index);  
  
        if (index == size)     //插入位置在末尾  
            linkLast(element);  
        else                     
            linkBefore(element, node(index));  
    }


查找index具体位置时调用了node(int index)方法,提高了查找index对应节点的效率,因为使用位移操作来判断从头部还是尾部开始找。

Node<E> node(int index) {  
        if (index < (size >> 1)) {    //size右移一位也就是如果index 小于 size/2 则从头开始查找  
            Node<E> x = first;  
            for (int i = 0; i < index; i++)  
                x = x.next;  
            return x;  
        } else {   //如果index 大于 size/2 则从尾部开始查找  
            Node<E> x = last;  
            for (int i = size - 1; i > index; i--)  
                x = x.prev;  
            return x;  
        }  
    }


3.Vector
Vector内部也是跟ArrayList一样,用动态数组实现,所以效率差不多,只是Vector是线程安全的。

3.容量扩容

Vector和ArrayList一样都使用动态数组,故增加元素的时候有时可能需要扩容操作。ArrayList使用ensureCapacityHelper(int minCapacity)方法。Vector调用ensureCapacity(int
minCapacity)的同步方法,方法内部再调用了ensureCapacityHelper(int minCapacity)方法。

它们容量扩容的逻辑都在grow方法中

(1)ArrayList的ensureCapacityHelper(int minCapacity)

public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != EMPTY_ELEMENTDATA)
            // any size if real element table
            ? 0
            // larger than default for empty table. It's already supposed to be
            // at default size.
            : DEFAULT_CAPACITY;

if (minCapacity > minExpand) {
            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;  //ArrayList容量大小
        int newCapacity = oldCapacity + (oldCapacity >> 1);  //扩容后的容量为旧容量的1.5倍
        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的ensureCapacityHelper(int minCapacity)最后调用了grow(int minCapacity),并将容量扩展为原来的1.5倍

(2)Vector

Vector扩展容量是根据capacityIncrement的,若容量增量系数(capacityIncrement) > 0,则将容器大小增加到capacityIncremen他,否则将容量增加一倍

public synchronized void ensureCapacity(int minCapacity) {
        if (minCapacity > 0) {
            modCount++;
            ensureCapacityHelper(minCapacity);
        }
    }
private void ensureCapacityHelper(int minCapacity) {
        // 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 + ((capacityIncrement > 0) ?  
                                         capacityIncrement : oldCapacity);//<span style="font-family: Calibri;">capacityIncrement<0则新容量为原来的2倍,否则增加capacityIncrement</span>

        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: