LinkedList、ArrayList、Vector、Stack的实现原理和差异

相互关系

    LinkedList、ArrayList、Vector 都继承自 AbstractList;都实现了 List 接口,主要包括 size(), isEmpty(), contains(Object), iterator(), toArray(), add(E), remove(), get(int), sort(), clear(), set(int, E), subList(int, int), listIterator() 等方法。
    LinkedList 实现了 Deque 接口(主要是对首尾元素的添加删除方法), Vector 和 ArrayList 实现了 RandomAccess 接口。
    它们都是泛型类,可以存放任意类型的对象。

public class LinkedList<E> extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

public class ArrayList<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

public class Vector<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

public class Stack<E> extends Vector<E>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    类的继承关系

AbstractCollection
    -> AbstractList
        -> AbstractSequentialList - > LinkedList
        -> ArrayList
        -> Vector ->  Stack     

    1
    2
    3
    4
    5

实现原理和线程安全性
LinkedList

    LinkedList 可以看做为一个双向链表,所有的操作都可以认为是一个双向链表的操作,实现了 List 和 Deque 接口。LinkList 可以很方便地在链表头或者链表尾插入数据,或者在指定结点前后插入数据,还提供了取走链表头或链表尾的结点,或取走中间某个结点的方法。
    LinkedList 没有同步方法,是线程不安全的。
    如果多个线程同时访问一个List,必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List list = Collections.synchronizedList(new LinkedList(…));
    成员变量: 

transient int size = 0;
transient Node<E> first; // 使用结点<Node>来存放数据的, first指向链表头
transient Node<E> last; // last指向链表尾

    1
    2
    3

    Node 数据结构

    private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;
        // more code
    }

    1
    2
    3
    4
    5
    6

ArrayList

    ArrayList实现了可变大小的数组。它允许所有元素,包括null。
    ArrayList没有同步,是线程不安全的。
    成员变量:

transient Object[] elementData; // 存放对象的数组,第一次插入数据时初始化为DEFAULT_CAPACITY=10大小
private int size; // 数组大小

    1
    2

    扩容:
        ArrayList 的容量 capacity 可随着不断添加新元素而自动增加,正常情况下每次增加当前数组大小的一半。
        扩容时拷贝旧数据生成一个 newCapacity 大小的新数组,然后将elementData指向新数组。
        扩容时机:
            add元素前,先确保 catacity>=size+1。
            当需要插入大量元素时,在插入前可以调用 ensureCapacity(int minCapacity) 方法来增加ArrayList的容量以提高插入效率, 参数 minCapacity 为希望调整到的最小容量。

Vector

    Vector也是一个类似于ArrayList的可变长度的数组类型,它的内部也是使用数组来存放数据对象的。
    Vector与ArrayList唯一的区别是,Vector是线程安全的,即它的大部分方法都包含有关键字synchronized,因此,若对于单一线程的应用来说,最好使用ArrayList代替Vector,因为这样效率会快很多(类似的情况有StringBuffer与StringBuilder);而在多线程程序中,为了保证数据的同步和一致性,可以使用Vector代替ArrayList实现同样的功能。
    成员变量:

protected Object[] elementData;
protected int elementCount;
protected int capacityIncrement; // 每次容量增长值,如果<=0,则每次增长当前数组大小。

    1
    2
    3
    4

Stack

    Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得 Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

总结
List     实现原理     线程安全性     备注
LinkedList     双向链表     不安全     相对于ArrayList,插入或增加效率高,查询效率低;使用数据频繁出入的情况。
ArrayList     数组     不安全     试用与数组变动不大,主要用来查询的情况。
Vector     数组     安全     
Stake     数组     安全     继承自Vector,添加额外方法实现后进先出的堆栈
---------------------
作者:maowenbei
来源:CSDN
原文:https://blog.csdn.net/maowenbei/article/details/80250771
版权声明:本文为博主原创文章,转载请附上博文链接!

posted @ 2019-06-25 19:35  天涯海角路  阅读(211)  评论(0)    收藏  举报