美文网首页Java面试题
ArrayList、LinkedList、Vector的区别

ArrayList、LinkedList、Vector的区别

作者: fanderboy | 来源:发表于2020-07-17 17:00 被阅读0次

    1.从存储数据结构分析

    ArrayList:数组

    Vector:数组

    LinkedList:双向链表
    数组:(数组属于顺序存储,用一段连续的内存位置来存储)可以根据下标快速查找,所以大部分情况下,查询快。但是如果要进行增删操作的时候,会需要移动修改元素后面的所有元素,所以增删的开销比较大,数组的对增删操作的执行效率低。而采用数组作为数据存储结构的ArrayList、Vector也存在这些特性,查询速度快(可以根据下标直接取,比迭代查找更快),增删慢。

    链表:(链表属于链接存储,用一组任意的存储单元来存储,不要求物理上相邻)增加和删除元素方便,增加或删除一个元素,仅需处理结点间的引用即可。就像人手拉手连成一排,要增加或删除某个人只要附近的两个人换一个人牵手,对已经牵好手的人没影响。无论在哪里换人耗费的资源和时间都是一样的。但是查询不方便,需要一个个对比,无法根据下标直接查找。而采用链表结构存储的LinkedList也有这些特性,增删方便,查询慢(指的是随机查询,不是顺序查询)。
    总结:
    因为CPU缓存会读入一段连续的内存,顺序存储符合连续的内存,所以顺序存储可以被缓存处理,而链接存储并不是连续的,分散在堆中,所以只能内存去处理。
    所以数组查询比链表要快。
    而数组大小固定,插入和删除都需要移动元素,链表可以动态扩充,插入删除不需要移动元素,只需要更改元素中的指针。所以链表的插入删除比数组效率高。

    2.从继承上分析


    image.png

    都实现了List接口,也就是说都实现了get(int location)、remove(int location)等“根据索引值来获取、删除节点的函数”。数组结构根据下标取值很容易,LinkedList双向列表的实现也比较简单,通过计数索引值实现,从链表长度的1/2开始查找,下标大了就从表头开始找,小了就从表尾开始找。

    3.从并发安全上分析

    Vector:线程安全

    ArrayList:非线程安全

    LinkedList:非线程安全

    4.Vector和ArrayList区别
    (1)Arraylist默认构造方法创建一个空数组,第一次添加元素时候,扩展容量为10

        /**
         * Shared empty array instance used for default sized empty instances. We
         * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
         * first element is added.
         */
        private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
        /**
         * Constructs an empty list with an initial capacity of ten.
         */
        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
    

    Vector默认构造方法创建一个大小为10的对象数组

     /**
         * Constructs an empty vector with the specified initial capacity and
         * capacity increment.
         *
         * @param   initialCapacity     the initial capacity of the vector
         * @param   capacityIncrement   the amount by which the capacity is
         *                              increased when the vector overflows
         * @throws IllegalArgumentException if the specified initial capacity
         *         is negative
         */
        public Vector(int initialCapacity, int capacityIncrement) {
            super();
            if (initialCapacity < 0)
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
            this.elementData = new Object[initialCapacity];
            this.capacityIncrement = capacityIncrement;
        }
    
        /**
         * Constructs an empty vector with the specified initial capacity and
         * with its capacity increment equal to zero.
         *
         * @param   initialCapacity   the initial capacity of the vector
         * @throws IllegalArgumentException if the specified initial capacity
         *         is negative
         */
        public Vector(int initialCapacity) {
            this(initialCapacity, 0);
        }
        /**
         * Constructs an empty vector so that its internal data array
         * has size {@code 10} and its standard capacity increment is
         * zero.
         */
        public Vector() {
            this(10);
        }
    

    (2)Arraylist第一次添加元素时候,扩展容量为10,之后的扩充算法:原来数组大小+原来数组的一半(也就是1.5倍)

      /**
         * 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 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);
        }
       /**
         * 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);// n + n / 2 扩容算式
            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);
        }
    

    Vector和Arraylist的扩容机制类似,与Vector不同的是,Vector分两种情况如果增量为0的情况下每次扩容容量是翻倍,即为原来的2倍,而当增量>0的时候,扩充为原来的大小加增量,而ArrayList是1.5倍。

    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、LinkedList、Vector的区别

        本文链接:https://www.haomeiwen.com/subject/lbgghktx.html