list的子类ArrayList,Linkedlist,Vector的测试效率与总结

  • list set map区别

  1. List,Set都是继承自Collection接口,Map则不是
  2. List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。) 
  3. Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。Map:适合储存键值对的数据  List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。
  4. LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;HashMap是非线程安全的,HashTable是线程安全的;StringBuilder是非线程安全的,StringBuffer是线程安全的。

  • 先来理清这几个爹的常见儿子:

Collection   
        |--------List 
                    |----------LinkedList 
                    |----------ArrayList 
                    |----------Vector 
                                     |-----Stack 
        |--------Set 
                    |----------HashSet 
                    |----------TreeSet 
Map 
        |---------HashMap 
        |---------TreeMap 
  • list的子类介绍 

 ArrayListVectorLinkedList
底层结构数组结构数组结构链表结 构
空间占用

存储区间连续

占用空间大,空间复杂度大

存储区间连续

占用空间大,空间复杂度大

存储区间离散

占用宽松,空间复杂度小

特点查询快,增删慢查询快,增删慢查询慢,增删快
安全性不安全,不同步,效率高安全的,同步的,效率低不安全,不同步,效率高
  • ArrayList,Vector,LinkedList

需求:模拟的数据的增删改查测试

// 计算添加所需的时间
	static long readList_add(List<Integer> list) {

		long start = System.currentTimeMillis();
		for (int i = 0; i < 300000; i++) {
			list.add(0, i);
		}

		return System.currentTimeMillis() - start;
	}

	public static void main(String[] args) {
		ArrayList<Integer> arrayList = new ArrayList<Integer>();
		System.out.println("ArrayList添加消耗的时间:" + readList_add(arrayList) + "毫秒");

		LinkedList<Integer> linkedList = new LinkedList<Integer>();
		System.out.println("LinkedList添加消耗的时间:" + readList_add(linkedList) + "毫秒");

		Vector<Integer> vector = new Vector<Integer>();
		System.out.println("Vector添加消耗的时间:" + readList_add(vector) + "毫秒");
	}

结果:

ArrayList添加消耗的时间:10514毫秒
LinkedList添加消耗的时间:13毫秒
Vector添加消耗的时间:10558毫秒

这里使用的是add(int index,e elemen)方法,在指定的下标下插入数据,list.add(0, i);在插入的数据始终放入第一位,新插入的元素就会把前一位插入的元素向后挤。所以结果就是list.get(0)就是获取的29999,也就是最新插入的数据,这样会产生一种幻觉就是倒序,其实不是的。

插入位置的选取对LinkedList有很大的影响,一直往数据中间部分插入删除的时候,ArrayList比LinkedList更快

原因大概就是当数据量大的时候,system.arraycopy的效率要比每次插入LinkedList都需要从端查找index和分配节点node来的更快。


下面测试删除

// 计算删除所需的时间
	static long readList_delete(List list) {
		long start = System.currentTimeMillis();
		for (int i = 0; i < list.size(); i++) {
			list.remove(i);//从头删
		}
		return System.currentTimeMillis() - start;
	}
public static void main(String[] args) {
		ArrayList<Integer> arrayList = new ArrayList<Integer>();
		for (int i = 0; i < 100000; i++) {
			arrayList.add(i);// 插入的时候始终在下标为0的位置插入,插入的新元素会向后移动
		}
		System.out.println("ArrayList删除消耗的时间:" + readList_delete(arrayList) + "毫秒");

		
		LinkedList<Integer> linkedList = new LinkedList<Integer>();
		for (int i = 0; i < 100000; i++) {
			linkedList.add(i);// 插入的时候始终在下标为0的位置插入,插入的新元素会向后移动
		}
		System.out.println("linkedList删除消耗的时间:" + readList_delete(linkedList) + "毫秒");
		
		
		Vector<Integer> vector = new Vector<Integer>();
		for (int i = 0; i < 100000; i++) {
			vector.add(i);// 插入的时候始终在下标为0的位置插入,插入的新元素会向后移动
		}
		System.out.println("Vector删除消耗的时间:" + readList_delete(vector) + "毫秒");
}

结果:

ArrayList删除消耗的时间:530毫秒
linkedList删除消耗的时间:2767毫秒
Vector删除消耗的时间:533毫秒

我曹,为什么???为什么linkedlist增删有时候都会落败?

因为:

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

但测试结果与理论不相符。ArrayList在添加、查找、删除的性能都优于LinkedList。

细细想一下,当顺序添加数据时,ArrayList的容量足够大,就不把时间浪费在扩容上,如果对象是很简单对象,在删除操作时移动数组也是足够快的。LinkedList是链表结构相对数组来说比较复杂,在添加数据操作上比较消耗时间,而在删除操作时,因为大部分时间都花费在查找上,所以删除操作时间变长。而vector效率很低,但是线程安全,多用于银行等操作。


下面在测试查询:

// 计算查询所需的时间
	static long readList_query(List<Integer> list) {
		long start = System.currentTimeMillis();
		for (int i = 0; i <= 10000; i++) {
			list.add(i);
		}
		for (int i = 0; i <= 10000; i++) {
			list.get(i);
		}
		return System.currentTimeMillis() - start;
	}

public static void main(String[] args) {
		ArrayList<Integer> arrayList = new ArrayList<Integer>();
		System.out.println("ArrayList查询消耗的时间:" + readList_query(arrayList) + "毫秒");

		LinkedList<Integer> linkedList = new LinkedList<Integer>();
		System.out.println("linkedList查询消耗的时间:" + readList_query(linkedList) + "毫秒");

		Vector<Integer> vector = new Vector<Integer>();
		System.out.println("Vector查询消耗的时间:" + readList_query(vector) + "毫秒");
}

结果:

ArrayList查询消耗的时间:3毫秒
linkedList查询消耗的时间:59毫秒
Vector查询消耗的时间:2毫秒

三个list的使用场景:

  1. ArrayList使用场景:因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销 
  2.   Vector使用场景: 如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。  
  3. LinkedList使用场景:经常有删除/插入操作而顺序遍历列表 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值