Java中List效率的比较

  inkfish原创,请勿商业性质转载,转载请注明来源(http://blog.csdn.net/inkfish
)。

  Java Collections Framework(JCF)
是Java SE中一个基本的类集,几乎所有的项目都会用到,其中的List
则是JCF中最最常用的一个接口。围绕List
接口,有很多实现,诸如常用的ArrayList
LinkedList
Vector
Stack
,还有Java5之后引入的CopyOnWriteArrayList
,也有不少List
的开源实现,如Apache commons-collections中的各类List
。(来源:http://blog.csdn.net/inkfish)

  这么多的List
实现,如何选择?他们的运行效率具体怎样?本篇文章将用具体的代码来检测其中最最常用的一些List
实现。(来源:http://blog.csdn.net/inkfish)

测试环境:

  处理器:Intel Core 2 Duo P8600 2.4GHz

  内存:2G

  硬盘:160G 7200rpm

  Java:SUN JDK 1.6.0_15

  开发环境:Eclipse 3.5

  第三方类库:Apache commons-lang 2.4、Apache commons-collections 3.2.1(来源:http://blog.csdn.net/inkfish)

主要测试对象:

  java.util.ArrayList;

  java.util.LinkedList;

  java.util.Stack;

  java.util.Vector;

  java.util.concurrent.CopyOnWriteArrayList;

  org.apache.commons.collections.FastArrayList;

  org.apache.commons.collections.list.TreeList;
(来源:http://blog.csdn.net/inkfish)

测试用例:

  1.测试List

   1.1顺序添加

   1.2随机插入

   1.3随机删除

   1.4随机访问

   1.5随机更新

   1.5顺序迭代

  2.测试List
在三种情况下的排序效率

   2.1初始时List
中元素已从小到大有序排列(最优情况)

   2.2初始时List
中元素已从大到小有序排列(最差情况)

   2.3初始时List
中元素随机排列,无序

  3.测试List
互相转换的效率

   3.1转化为TreeList

   3.2转化为ArrayList

   3.3转化为LinkedList

   3.4转化为CopyOnWriteArrayList

   3.5转化为Vector
(来源:http://blog.csdn.net/inkfish)

测试代码:
(来源:http://blog.csdn.net/inkfish)

package test;
import static java.lang.System.out;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.commons.collections.FastArrayList;
import org.apache.commons.collections.list.TreeList;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.StopWatch;
@SuppressWarnings("unchecked")
public class ListPerformance {
public static void main(String[] args) {
ListPerformance test = new ListPerformance(10 * 10000);
out.print(StringUtils.center("Test List Performance: loop=" + test.loop, 80, '-'));
out.printf("/n%20s%10s%10s%10s%10s%10s%10s", "", "add", "insert", "remove", "get", "set",
"iterator");
test.benchmark(new FastArrayList());
test.benchmark(new TreeList());
test.benchmark(new ArrayList());
test.benchmark(new LinkedList());
test.benchmark(new CopyOnWriteArrayList());
test.benchmark(new Vector());
test.benchmark(new Stack());
//2.测试排序
out.print("/n/n");
out.print(StringUtils.center("Test List sort Performance: loop=" + test.loop, 80, '-'));
out.printf("/n%20s%10s%10s%10s", "", "optimize", "worst", "random");
test.benchmarkSort(new FastArrayList());
test.benchmarkSort(new TreeList());
test.benchmarkSort(new ArrayList());
test.benchmarkSort(new LinkedList());
//test.benchmarkSort(new CopyOnWriteArrayList());//UnsupportedOperationException
test.benchmarkSort(new Vector());
test.benchmarkSort(new Stack());
//3.测试各种数据结构间转化
out.print("/n/n");
out.print(StringUtils.center("Test List convert Performance: loop=" + test.loop, 80, '-'));
out.printf("/n%20s%10s%10s%10s%10s%10s", "", "Tree", "Array", "Linked", "CopyOnWrite",
"Vector");
test.benchmarkConvert(new FastArrayList());
test.benchmarkConvert(new TreeList());
test.benchmarkConvert(new ArrayList());
test.benchmarkConvert(new LinkedList());
test.benchmarkConvert(new CopyOnWriteArrayList());
}
/**测试循环次数*/
private int loop = 10000;
public ListPerformance(int loop) {
this.loop = loop;
}
public void benchmark(List list) {
out.printf("/n%20s", list.getClass().getSimpleName());
int j;
StopWatch watch = null;
//1.测试顺序性能(Add)
(watch = new StopWatch()).start();
for (int i = 0; i < loop; i++) {
list.add(new Integer(i));
}
watch.stop();
out.printf("%10d", watch.getTime());
//2.测试随机插入性能(Random insert)
(watch = new StopWatch()).start();
for (int i = 0; i < loop; i++) {
j = (int) (Math.random() * loop);
list.add(j, new Integer(-j));
}
watch.stop();
out.printf("%10d", watch.getTime());
//3.测试随机索引删除(Random remove)
(watch = new StopWatch()).start();
for (int i = 0; i < loop; i++) {
j = (int) (Math.random() * loop);
list.remove(j);
}
watch.stop();
out.printf("%10d", watch.getTime());
//4.测试随机取数性能(Random get)
(watch = new StopWatch()).start();
for (int i = 0; i < loop; i++) {
j = (int) (Math.random() * loop);
list.get(j);
}
watch.stop();
out.printf("%10d", watch.getTime());
//5.测试随机更新性能(Random set)
(watch = new StopWatch()).start();
for (int i = 0; i < loop; i++) {
j = (int) (Math.random() * loop);
list.set(j, j);
}
watch.stop();
out.printf("%10d", watch.getTime());
//6.测试迭代性能(Iterator)
(watch = new StopWatch()).start();
Iterator<Object> iter = list.iterator();
while (iter.hasNext()) {
iter.next();
}
watch.stop();
out.printf("%10d", watch.getTime());
}
public void benchmarkConvert(List list) {
out.printf("/n%20s", list.getClass().getSimpleName());
StopWatch watch = null;
//1.转TreeList
(watch = new StopWatch()).start();
new TreeList(list);
watch.stop();
out.printf("%10d", watch.getTime());
//2.转ArrayList
(watch = new StopWatch()).start();
new ArrayList(list);
watch.stop();
out.printf("%10d", watch.getTime());
//3.转LinkedList
(watch = new StopWatch()).start();
new LinkedList(list);
watch.stop();
out.printf("%10d", watch.getTime());
//4.转CopyOnWriteArrayList
(watch = new StopWatch()).start();
new CopyOnWriteArrayList(list);
watch.stop();
out.printf("%10d", watch.getTime());
//5.转Vector
(watch = new StopWatch()).start();
new Vector(list);
watch.stop();
out.printf("%10d", watch.getTime());
}
public void benchmarkSort(List list) {
out.printf("/n%20s", list.getClass().getSimpleName());
StopWatch watch = null;
//1.顺序List
for (int i = 0; i < loop; i++) {
list.add(new Integer(i));
}
(watch = new StopWatch()).start();
Collections.sort(list);
watch.stop();
out.printf("%10d", watch.getTime());
//2.逆序List
for (int i = loop - 1; i > 0; i--) {
list.add(new Integer(i));
}
(watch = new StopWatch()).start();
Collections.sort(list);
watch.stop();
out.printf("%10d", watch.getTime());
//3.随机顺序List
for (int i = 0, j = 0; i < loop; i++) {
j = (int) (Math.random() * loop);
list.add(new Integer(j));
}
(watch = new StopWatch()).start();
Collections.sort(list);
watch.stop();
out.printf("%10d", watch.getTime());
}
}

测试结果:
(来源:http://blog.csdn.net/inkfish)

-----------------------Test List Performance: loop=100000-----------------------
add insert remove get set iterator
FastArrayList 16 8609 8360 15 47 0
TreeList 110 187 156 47 110 78
ArrayList 15 8313 8344 0 15 0
LinkedList 47 50110 80671 59016 55391 78
CopyOnWriteArrayList 54016 484003 370891 16 105406 0
Vector 15 8266 8328 0 16 0
Stack 31 8281 8266 0 16 0
--------------------Test List sort Performance: loop=100000---------------------
optimize worst random
FastArrayList 47 78 110
TreeList 15 47 110
ArrayList 32 47 78
LinkedList 15 109 125
Vector 0 63 94
Stack 16 46 78
-------------------Test List convert Performance: loop=100000-------------------
Tree Array LinkedCopyOnWrite Vector
FastArrayList 0 0 0 0 0
TreeList 0 0 0 0 0
ArrayList 0 0 0 0 0
LinkedList 0 0 0 0 0
CopyOnWriteArrayList 0 0 0 0 0

结论:

  1.随机插入、随机删除操作中,用TreeList
效率最高;

  2.在只需要追加、迭代的环境下,LinkedList
效率最高;

  3.平均效率来讲,ArrayList
相对平衡,但如果海量随机操作,还是会造成性能瓶颈;

  4.CopyOnWriteArrayList
因为线程安全的原因,致使性能降低很多,所以慎用;

  5.Vector
没有传说中那么低的效率;

  6.让Stack
来做List
的事可以,不过语义上Stack
不应该做过多的List
的事情;

  7.在排序中,ArrayList
具有最好的性能,TreeList
平均性能也不错,LinkedList
的排序效率受元素初始状态的影响很大。

  8.各种List
间转换几乎没有时间损耗。(来源:http://blog.csdn.net/inkfish)

时间: 2024-12-19 07:36:01

Java中List效率的比较的相关文章

java频繁连接、调用oracle数据库的某存储过程,且存储过程返回游标在JAVA中遍历,使用什么连接,或什么方式效率比较好??

问题描述 java频繁连接.调用oracle数据库的某存储过程,且存储过程返回游标在JAVA中遍历,使用什么连接,或什么方式效率比较好??

java中为什么有的变量声明而不赋值?

问题描述 java中为什么有的变量声明而不赋值? java中为什么有的变量声明而不赋值?而有的就值,那什么情况下要赋值,什么情况下不赋值 解决方案 比如对象变量,而调用这个变量的构造函数非常耗费时间,所以我们等用到的时候再创建,如果程序运行完都不访问它,就根本不创建,这样可以提高效率. 对于简单变量,比如int float一类的,建议随手给一个初始值. 解决方案二: 你这个问题给你举个例子,你应该就能理解了 例如: int a; 这是只声明不赋值,则只会在内存的栈区创建引用,堆中并无此引用的指向

Java中static、this、super、final用法

一.static  请先看下面这段程序:   public class Hello{     public static void main(String[] args){ //(1)       System.out.println("Hello,world!");   //(2)     }   } 看过这段程序,对于大多数学过Java 的从来说,都不陌生.即使没有学过Java,而学过其它的高级语言,例如C,那你也应该能看懂这段代码的意思.它只是简单的输出"Hello,w

Thinking:Java中static、this、super、final用法

Thinking:Java中static.this.super.final用法   本篇旨在帮助准备学习Java以及刚接触Java的朋友认识.掌握和使用static.this.super.final这几个关键字的使用.Java博大精深,我也是一位正在学习和使用Java的爱好者,文中难免有不妥之处,欢迎指正. 一.static 请先看下面这段程序:   public class Hello{    public static void main(String[] args){ //(1)     

详解Java中的指针、引用及对象的clone

对象|详解 Java语言的一个优点就是取消了指针的概念,但也导致了许多程序员在编程中常常忽略了对象与引用的区别,本文会试图澄清这一概念.并且由于Java不能通过简单的赋值来解决对象复制的问题,在开发过程中,也常常要要应用clone()方法来复制对象.本文会让你了解什么是影子clone与深度clone,认识它们的区别.优点及缺点.看到这个标题,是不是有点困惑:Java语言明确说明取消了指针,因为指针往往是在带来方便的同时也是导致代码不安全的根源,同时也会使程序的变得非常复杂难以理解,滥用指针写成的

浅谈Java中的存储空间类型

在Thinking in java里,列举了Java的六种存储类型1.寄存器编写过汇编程序的应该对寄存器非常熟悉,那时候用的ax,bx,cx,dx等等.寄存器在CPU里面,所以速度特别快,但是数量非常有限.在java中无法直接和寄存器打交道,不过在c中是可以声明寄存器变量的. 2.栈空间写过汇编的肯定感到非常亲切,在汇编程序里不就是压栈和出栈吗?有一个指针控制栈空间,分配空间是栈指针上移,就是push操作,释放空间指针下移,就是pop操作.当然C和C++也主要是通过栈分配空间的.因为只要压栈和出

java中的易混问题收集

问题 第一,final, finally, finalize的区别. final?修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 abstract的,又被声明为final的.将变量或方法声明为final,可以保证它们在使用中不被改变.被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改.被声明为final的方法也同样只能使用,不能重载 finally?再异常处理时提供 finally 块来执行任

Java中异常机制的深入研究

由于本文旨在探讨Java"异常机制"的深层原理,因此关于"异常"的使用方法都不做详细说明.首先看一段非常熟悉的用于打开一个文件的C程序段: FILE *fp;fp=fopen(filename,"rw");if(fp==NULL){ printf("cannot open file\n"); exit(0);} 在这段程序中,if条件语句中的一段用来处理没有找到指定文件,或者其它原因无法正确打开指定文件.可是如果遇到一个责任心

JAVA中几个易混淆关键词的理解

行为规范了你能对对象发出的请求.你的CLASS,也就是对象,也就是MM,你把她设计出来了,而且你很BT,只给她设计了两个行为:爱我()和MAKE爱与我().那么她便不可能接受其它客户端class(某个帅哥?)的请求,如果在某个class里,你写成了MM.爱F4(),那么编译器就会出错. 你理所当然把MM的属性设成美,你不希望别人来改变这个事实,那么,你就要把这个属性定义为private,这样MM便不会在第二天醒来成为传说中的KL.这在第一章里标题为:被隐藏的实施细节.一个属性,有四种修饰符,pu