ArrayList与LinkedList的区别 ?

Posted keep-go-on

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList与LinkedList的区别 ?相关的知识,希望对你有一定的参考价值。


区别

  1. 数据结构不同。Array是数组,Linked是链表。
  2. 适用场景不同。由于结构不同,Array更适合随机查询,而Linked更适合删除和添加。由于结构不同,导致两者对查询,新增和删除的时间复杂度不同。
  3. 由于LinkedList实现了Deque接口,因此LinkedList可以作为队列使用。
  4. ArrayList添加元素时需要计算扩容,由于LinkedList是双链表,因此LinkedList是不要扩容的。

相同点

  1. ArrayList和LinkedList都实现了List接口
  2. 都可以作为列表使用,只是作为列表时的查询,新增,删除的时间复杂度不同。

ArrayList与LinkedList的add谁更快 ?

这里没有标准答案 ?

如果向尾部添加一个元素

如果ArrayList新增时不需要扩容,理论上不需要再去申请新的内存因此ArrayList更快。

如果ArrayList新增元素时需要进行扩容,则LinkedList更快,ArrayList每次扩容都会扩容当前的1.5倍,代价还是很昂贵的(具体见下方简介)。

如果向中间位置添加元素

由于ArrayList需要移动元素,因此LinkedList更快。


java集合框架图

在这里插入图片描述

ArrayList扩容

每次向ArrayList添加元素时,都会计算元素的数量是否已经超出数组的容量,如果超出,数组将会进行扩容,以满足添加数据的需求。ArrayList扩容是通过一个公开的方法ensureCapacity(int minCapacity)来实现。

在实际添加大量元素前,我也可以使用ensureCapacity来手动增加ArrayList实例的容量,以减少递增式再分配的数量。

数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍。

这种操作的代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张:

  1. 创建ArrayList实例时,就指定其容量,以避免数组扩容的发生。
  2. 根据实际需求,通过调用ensureCapacity方法来手动增加ArrayList实例的容量。

新增时源代码

 public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 计算容量
        elementData[size++] = e;
        return true;
    }

扩容源代码


	//可通过该方法手动扩容
    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

    private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

	// 最终执行扩容的方法
    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;
    }
  

扩容过程如下图所示 :
在这里插入图片描述

以上是关于ArrayList与LinkedList的区别 ?的主要内容,如果未能解决你的问题,请参考以下文章

ArrayList与LinkedList的区别 ?

arraylist与linkedlist的区别与性能测试

ArrayList与LinkedList区别

ArrayList 与 LinkedList 的不区别?

Java中ArrayList和LinkedList区别 时间复杂度 与空间复杂度

arraylist和linkedlist的区别