JAVA集合类之ArrayList和LinkedList性能比较

关于ArrayList和LinkedList这两个集合类的性能,网上很多文章表示:ArrayList的插入性能要比LinkedList差。今天突然想测试下,这个结论是否准确。

编写了如下代码:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Demo {

	public static void main(String[] args) {

		int count = 1000000;	//循环次数
		System.out.println("循环 " + count + " 次,ArrayList LinkedList 尾部插入性能测试:");

		List<Integer> lst = new ArrayList<Integer>();
		List<Integer> link = new LinkedList<Integer>();

		new Demo().testInsert(lst, count);
		new Demo().testInsert(link, count);

		int index = 0;			//插入位置
		count = 90000;
		System.out.println("\n循环 " + count + " 次,ArrayList LinkedList 指定位置插入性能测试:");

		lst = new ArrayList<Integer>();
		link = new LinkedList<Integer>();
		new Demo().testInsertForIndex(lst, count, index);
		new Demo().testInsertForIndex(link, count, index);

	}

	/**
	 * 向默认位置插入元素
	 * @param count	循环次数
	 */
	public void testInsert(List<Integer> lst, int count){
		long bTime = System.currentTimeMillis();
		for(int i=0; i<count; i++){
			lst.add(1);
		}
		long eTime = System.currentTimeMillis();

		System.out.println(lst.getClass().getName() + " 共耗时:" + (eTime - bTime) + " ms");
	}

	/**
	 * 向指定位置插入元素
	 * @param count	循环次数
	 * @param index	插入位置
	 */
	public void testInsertForIndex(List<Integer> lst, int count, int index){
		long bTime = System.currentTimeMillis();
		for(int i=0; i<count; i++){
			lst.add(index,1);
		}
		long eTime = System.currentTimeMillis();

		System.out.println(lst.getClass().getName() + " 共耗时:" + (eTime - bTime) + " ms");
	}
}

执行结果如下:

循环 1000000 次,ArrayList LinkedList 尾部插入性能测试:
java.util.ArrayList 共耗时:56 ms
java.util.LinkedList 共耗时:192 ms

循环 90000 次,ArrayList LinkedList 指定位置插入性能测试:
java.util.ArrayList 共耗时:3885 ms
java.util.LinkedList 共耗时:5 ms

根据结果发现,在都使用add(E e)函数添加元素时,LinkedList的性能反而不如ArrayList。那这到底是为何?

我们来看看具体的源码:

ArrayList的add(E e)函数

public boolean add(E e) {
    ensureCapacity(size + 1);  //数组扩容
    elementData[size++] = e;
    return true;
}

第一行代码:用于给ArrayList中的元素数组进行扩容,且先判断是否需要扩容,如果需要则扩容算法为:目前容量*3/2+1

第二行代码:向元素数组的尾部追加新元素

LinkedList的add(E e)函数

public boolean add(E e) {
    addBefore(e, header);
     return true;
}

private Entry<E> addBefore(E e, Entry<E> entry) {
    Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
    newEntry.previous.next = newEntry;
    newEntry.next.previous = newEntry;
    size++;
    modCount++;
    return newEntry;
}

addBefore函数首先创建一个新的Entry节点,并插入到链接表,然后分别调整新节点的前一节点的向后引用和后一节点的向前引用。

看了这两段代码前面的结论也就有了答案。

我们再来看看为什么向指定位置插入时,性能差距如此之大?

ArrayList的add(int index, E element)函数

public void add(int index, E element) {
    if (index > size || index < 0)
        throw new IndexOutOfBoundsException(
		"Index: "+index+", Size: "+size);

    ensureCapacity(size+1);  // Increments modCount!!
    System.arraycopy(elementData, index, elementData, index + 1,size - index);
    elementData[index] = element;
    size++;
}

此处可以看到每插入一个元素都会使用System.arraycopy进行数组的复制,可想而知这效率会有多低。

LinkedList的add(int index, E element)函数

public void add(int index, E element) {
    addBefore(element, (index==size ? header : entry(index)));
}

此处,依然调用了addBefore函数,性能与add(E e)没有差异。

总结:作为coder,每个细节都应该自己进行验证,不能人云亦云。

时间: 2024-12-17 19:09:11

JAVA集合类之ArrayList和LinkedList性能比较的相关文章

Java中针对 ArrayList和LinkedList 的区别

一般大家都知道ArrayList和LinkedList的大致区别:      1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构.      2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针.      3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据. ArrayList和LinkedList是两个集合类,用于存储一系列的对象引用

java 集合类源码分析--linkedlist

一.源码解析 1. LinkedList类定义2.LinkedList数据结构原理3.私有属性4.构造方法5.元素添加add()及原理6.删除数据remove()7.数据获取get()8.数据复制clone()与toArray()9.遍历数据:Iterator()二.ListItr 一.源码解析 1. LinkedList类定义. public class LinkedList<E> extends AbstractSequentialList<E> implements List

通过自己实现java中的ArrayList和LinkedList 深入理解数据结构---&quot;表&quot;

杂谈最基本数据结构--"表": 表结构是一种最基本的数据结构,最常见的实现是数组,几乎在每个程序每一种开发语言中都提供了数组这个顺序存储的线性表结构实现. 什么是线性表? 由0个或多个数据元素组成的有限序列.如果没有元素,称为空表,如果存在多个元素,则第一个元素无前驱,最后一个元素无后继,其他元素元素都有且只有一个前驱和后继. ArrayList和LinkedList ArrayList和LinkedList是顺序存储结构和链式存储结构的表在java语言中的实现. ArrayList提

java集合(ArrayList,Vector,LinkedList,HashSet,TreeSet的功能详解)

说起集合,我们会潜意识里想到另外一个与之相近的名词——数组,OK!两者确实有相似之处,但也正是这点才是我们应该注意的地方,下面简单列出了两者的区别(具体功能的不同学习这篇文章后就会明白了): 数组 长度固定 既可以存储基本数据类型,也能存储引用数据类型 一个数组中的元素类型必一致 集合 长度可变 只能存储引用数据类型 一个集合中的元素类型可以是任意的引用类型 一.集合概述 Collection<E> 父接口 List<E> 子接口 ArrayList<E>类 Vecto

java集合类之ArrayList详解

一.ArrayList源码分析 1.全局变量 (1)默认容量(主要是通过无参构造函数创建ArrayList时第一次add执行扩容操作时指定的elementData的数组容量为10) private static final int DEFAULT_CAPACITY = 10; (2)空的对象数组(当通过指定容量的构造方法创建ArrayList时指定给elementData,用于区分DEFAULTCAPACITY_EMPTY_ELEMENTDATA,比如说在得到最小扩容容量时判断elementDa

JAVA集合类之ArrayList源码分析

ArrayList继承自AbstractList抽象类,实现了List接口.  public class ArrayList<E> extends AbstractList<E>         implements List<E>, RandomAccess, Cloneable, java.io.Serializable ArrayList类中存储数据用的是Object类型的数组 private transient Object[] elementData; 此处的

Java集合之ArrayList和LinkedList的实现原理

ArrayList实现可变数组的原理: 当元素超出数组内容,会产生一个新数组,将原来数组的数据复制到新数组中,再将新的元素添加到新数组中. ArrayList:是按照原数组的50%来延长,构造一个初始容量为10的空列表 用ArrayList模拟数组: 1 package iterater.patten.design; 2 3 //探索ArrayList实现的可变数组的原理,用ArrayList实现一个容器存储对象 4 public class ArrayList { 5 Object[] obj

JAVA Vector和ArrayList使用及性能比较

  相同点: 都继承于AbstractList,并且实现List接口 都实现了RandomAccess和Cloneable接口 默认数组容量是10个 都支持Iterator遍历 不同点: ArrayList是非线程安全: 而Vector是线程安全的,它的函数都是synchronized的,即都是支持同步的 序列化支持不同: ArrayList实现了java.io.Serializable接口 容量增加数量不同: 容量不足时,"ArrayList新的容量"="(原始容量x3)/

Java集合类(1):ArrayList

学习Java的集合类 (1)成员变量以及初始化 private static final int DEFAULT_CAPACITY = 10; private static final Object[] EMPTY_ELEMENTDATA = {}; private transient Object[] elementData; private int size;  默认的大小为10. EMPTY_ELEMENTDATA是用于无参初始化,即一个等于null的对象数组. elemenData则用于