java List系(ArrayList,LinkedList,Vector)的比较


主要是复习一下以前学过的知识,也许还能帮助一下刚学习java的新手^-^

所以我也开通了自己的博客


言归正传,网上讲java List的博客也不少,但是我最近看了一本《数据结构与算法分析 java语言描述》,里面对list实现类的讲解还不错,也让我多他们有了更好一点的理解,所以我觉得我还是从这里开始吧,也把自己这方面的知识再巩固一下^-^.


我以前的理解:

ArrayList:提供了List可增长数组的实现,对于随机的get,set调用花费常数时间(即性能更好),但是其对于非末端的add,remove往往花费对数时间(性能比较差)。
Vector:与ArrayList基本一样,但其是线程安全的,所以牺牲一部分性能比ArrayList略差
LinkedList:提供了List的双链表实现,对于随机add,remove往往开销更小,但不易做索引,故随机get,set往往性能更差

实际环境操作:

环境:jdk1.8,Eclipse,以下测试都具有一定的片面性,但我觉得大致能体现一些东西,如有错误,希望指教^-^
1.尾部add操作:
public static void main(String[] args) {
		
		ArrayList<Integer> list1 = new ArrayList<>();
		LinkedList<Integer> list2 = new LinkedList<>();
		Vector<Integer> list3 = new Vector<>();
		
		
		
		new Thread(
				new Runnable() {
					public void run() {
						makeList1(list1, 30000);
					}
				}).start();
		
		new Thread(
			new Runnable() {
				public void run() {
					makeList1(list2, 30000);
				}
			}).start();
		
		new Thread(
				new Runnable() {
					public void run() {
						makeList1(list3, 30000);
					}
				}).start();
		
		
	}


public static List<Integer> makeList1(List<Integer> oo , int n) {
		
		oo.clear();
		Long begin = System.currentTimeMillis();
		for(int i = 0 ; i < n ; i++) {
			oo.add(i);			//1
			oo.add(0 , i);			//2
			oo.add(i/2 , i);		//3
		}
		System.out.println(oo.getClass().getName() + ":我是添加方法:" + (System.currentTimeMillis() - begin));
		return oo;
	}


结果:我发现若在main里面逐一调用,先后顺序对结果有一定影响,故使用多线程调用保证公平
第一次运行: 第二次运行: 第三次运行:
java.util.ArrayList:我是添加方法:32 java.util.ArrayList:我是添加方法:43 java.util.LinkedList:我是添加方法:43
java.util.Vector:我是添加方法:32 java.util.Vector:我是添加方法:43 java.util.Vector:我是添加方法:37
java.util.LinkedList:我是添加方法:29 java.util.LinkedList:我是添加方法:43 java.util.LinkedList:我是添加方法:40

结论:可以看出,对于尾部add操作,三种列表的性能几乎没有相同,也可改变n大小,结果消耗时间几乎为线性增长(为o(N))。当n很大时不能保持o(N),我个人认为是我机器的原因。

2.头部add操作:将1操作中的makeList1方法中1,3注释,消除2的注释
n=2000运行: n=20000运行: n=200000运行:
java.util.ArrayList:我是添加方法:2 java.util.Array List:我是添加方法:49 java.util.ArrayList:我是添加方法:5274
java.util.LinkedList:我是添加方法:1 java.util.LinkedList:我是添加方法:5 java.util.LinkedList:我是添加方法:25
java.util.Vector:我是添加方法:3 java.util.Vector:我是添加方法:47 java.util.Vector:我是添加方法:5285

结论:对于头部操作LinkedList消耗时间依然保持线性增长(o(N)),但ArrayList,Vector几乎已(o(N^2))增长。

3.中部操作:将makeList1方法中1,2注释,消除3的注释
n=2000运行: n=20000运行: n=80000运行:
java.util.ArrayList:我是添加方法:1 java.util.ArrayList:我是添加方法:33 java.util.ArrayList:我是添加方法:667
java.util.Vector:我是添加方法:1 java.util.Vector:我是添加方法:23 java.util.Vector:我是添加方法:670
java.util.LinkedList:我是添加方法:5 java.util.LinkedList:我是添加方法:294 java.util.LinkedList:我是添加方法:27950


结论:这个结果让我有一些意外,原因应该是在中部add时LinkedList一样要去遍历寻找index,而ArrayList只需把一般元素往后移动。故LinkedList只在前端时性能操作ArrayList;

4.get操作:
<pre name="code" class="java">public static void getList1(List<Integer> oo){
		int total = 0;
		Long begin = System.currentTimeMillis();
		for(int i = 0 ; i < oo.size() ; i++) {
			total += oo.get(i);
		}
		System.out.println(oo.getClass().getName() + ":get运行时间:" + (System.currentTimeMillis() - begin) +"结果" + total);
	}
getList1(makeList1(list2, 20000));//run方法里面的函数改为这个

 
 
 
 
public static void getList1(List<Integer> oo){
		int total = 0;
		Iterator<Integer> itr = oo.iterator();
		
		Long begin = System.currentTimeMillis();
		while(itr.hasNext()){
			total += itr.next();
		}
		System.out.println(oo.getClass().getName() + ":get运行时间:" + (System.currentTimeMillis() - begin) +"结果" + total);
	}


n=20000运行: n=60000运行:
java.util.ArrayList:我是添加方法:2 java.util.ArrayList:我是添加方法:10
java.util.ArrayList:get运行时间:2结果199990000 java.util.ArrayList:get运行时间:2结果1799970000
java.util.LinkedList:我是添加方法:5 java.util.LinkedList:我是添加方法:6
java.util.LinkedList:get运行时间:176结果199990000 java.util.LinkedList:get运行时间:1534结果1799970000
java.util.Vector:我是添加方法:3 java.util.Vector:我是添加方法:8
java.util.Vector:get运行时间:2结果199990000 java.util.Vector:get运行时间:6结果1799970000


当使用下面的getList1方法时,三者性能几乎误差,有兴趣的可以试试
结论:ArrayList还有Vector花费时间基本保持线性,LinkedList呈o(N^2)增长,set操作与个体操作结果基本一致。

5.遍历remove操作:
public static void removeList1(List<Integer> oo) {
		
		Iterator<Integer> itr = oo.iterator();
		Long begin = System.currentTimeMillis();
		while(itr.hasNext()){
			if(itr.next() % 3 == 0) itr.remove();
		}
		
		System.out.println(oo.getClass().getName() + "我是删除方法:" + (System.currentTimeMillis() - begin));
	}
</pre><pre name="code" class="java">removeList1(makeList1(list1, 300000));//将run方法内容改成这样


n=60000运行: n=600000运行:
java.util.LinkedList我是删除方法:9 java.util.LinkedList我是删除方法:17
java.util.ArrayList我是删除方法:134 java.util.ArrayList我是删除方法:3797
java.util.Vector我是删除方法:139 java.util.Vector我是删除方法:3802

结论:LinkedList操作时间保持线性,Vector,ArrayList呈O(N^2)

6.随机remove操作:
public static void removeList1(List<Integer> oo) {
		
		int n = oo.size()/2 ;
		Long begin = System.currentTimeMillis();
		for(int i = n; n > 0 ; n-- ){
			oo.remove(i);
		}
		
		System.out.println(oo.getClass().getName() + "我是删除方法:" + (System.currentTimeMillis() - begin));
	}

n=3000运行: n=9000运行:
java.util.ArrayList我是删除方法:1 java.util.ArrayList我是删除方法:4
java.util.Vector我是删除方法:1 java.util.Vector我是删除方法:3
java.util.LinkedList我是删除方法:5 java.util.LinkedList我是删除方法:20

结论:此时LinkedList性能并不如ArrayList,Vector

总结:

对比以上数据,发现:只要是在进行随机的操作时,LinkedList性能总是不如ArrayList,Vector。而在非随机(Iterator遍历的情况下)LinkedList在进行增加,删除性能性能总体是优于ArrayList,Vector

故,我认为在你要时常进行随机操作的数据时,你应该用ArrayList或者Vector。在不需要时常随时操作的时候用LinkedList



发现一个问题,为什么在我的实践中vector好多时候并没有比ArrayList性能差???难道是因为我用了多线程?


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值