Skip to the content.

Java中ArrayList和LinkedList区别

1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 

ArrayList底层的实现是数组,所以用下标访问的速度比较快,但是插入和删除元素,会有移动元素的开销,所以速度比LinkedList差。 LikedList底层是链表实现的,所以插入和删除元素时间复杂度较LinkedList好,但是随即访问需要遍历元素,所以效率比ArrayList差。 一般情况下,用ArrayList就可以了,如果涉及到频繁的插入和删除元素,这个时候考虑使用LinkedList,另外Java里面的Queue和Stack也是依赖LinkedList实现的。

ArrayList


    public E get(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

        return (E) elementData[index];
    }
	//将element添加到ArrayList的指定位置  
	public void add(int index, E element) {  
    	rangeCheckForAdd(index);  
  
    	ensureCapacityInternal(size + 1);  // Increments modCount!!  
    	//将index以及index之后的数据复制到index+1的位置往后,即从index开始向后挪了一位  
    	System.arraycopy(elementData, index, elementData, index + 1,  
                     size - index);   
    	elementData[index] = element; //然后在index处插入element  
    	size++;  
	}  
	//删除ArrayList指定位置的元素  
	public E remove(int index) {  
    	rangeCheck(index);  
  
    	modCount++;  
    	E oldValue = elementData(index);  
  
    	int numMoved = size - index - 1;  
    	if (numMoved > 0)  
        	//向左挪一位,index位置原来的数据已经被覆盖了  
        	System.arraycopy(elementData, index+1, elementData, index,  
                         numMoved);  
    	//多出来的最后一位删掉  
   	 	elementData[--size] = null; // clear to let GC do its work  
  
    	return oldValue;  
	}  

LinkedList

  public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
  //定位index处的节点  
    Node<E> node(int index) {
        // assert isElementIndex(index);
      //index<size/2时,从头开始找  
        if (index < (size >> 1)) {
            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;
        }
    }
//在index个节点之前添加新的节点  
public void add(int index, E element) {  
    checkPositionIndex(index);  
  
    if (index == size)  
        linkLast(element);  
    else  
        linkBefore(element, node(index));  
}
//删除第index个节点  
public E remove(int index) {  
    checkElementIndex(index);  
    return unlink(node(index));  
}  

通过阅读底层代码我们发现它是使用查找的方式获取指定元素的:就是将整个LinkedList的size除以2,然后与index进行比较 如果大于size/2 则倒序循环访问直到size/2位置查找指定位置的数据。如果index小于size/2,则顺序访问直到size/2位置找到对应元素.

什么场景下更适宜使用LinkedList,而不用ArrayList

在很多场景下ArrayList更受欢迎,但是还有些情况下LinkedList更为合适。譬如:

  1. 你的应用不会随机访问数据。因为如果你需要LinkedList中的第n个元素的时候,你需要从第一个元素顺序数到第n个数据,然后读取数据。

  2. 你的应用更多的插入和删除元素,更少的读取数据。因为插入和删除元素不涉及重排数据,所以它要比ArrayList要快。

以上就是关于ArrayList和LinkedList的差别。你需要一个不同步的基于索引的数据访问时,请尽量使用ArrayList。ArrayList很快,也很容易使用。但是要记得要给定一个合适的初始大小,尽可能的减少更改数组的大小

总结

1.对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。

2.在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。

3.LinkedList不支持高效的随机元素访问。

4.ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间

可以这样说:当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。

Star 我的GitHub

# Back