ArrayList与LinkedList 存储 插入 遍历时间比较与解释

知识提示: Java中ArrayList使用数组实现的。 LinkedList的使用双向链表实现的。
对于这两种数据结构。数组:遍历快,插入,删除慢。链表:遍历慢,插入,删除慢。若想详细了解集合的其他基础知识建议参考:集合干货

android 如何将List对象保存 java list存储对象_java


下面开始今天的分享(瞎扯),😂

1.分别创建ArrayList和LinkedList集合。

List<Integer> csp = new ArrayList<Integer>();
		//加入ArrayList集合:
		//以毫秒为单位的当前时间和午夜,
		//1970年1月1日UTC(协调世界时,又称世界统一时间、世界标准时间、国际协调时间)。
				long start = System.currentTimeMillis();
				for (int i = 0; i < 100000; i++) {
					csp.add(new Integer(i));
				}
				long end = System.currentTimeMillis();
				System.out.println("加入ArrayList集合的时间"+(end-start)+"毫秒");
		
				List<Integer> cspp = new LinkedList<Integer>();
		//加入LinkedList集合:
				long startc = System.currentTimeMillis();
				for (int i = 0; i < 100000; i++) {
					cspp.add(new Integer(i));
				}
				long endc = System.currentTimeMillis();
				System.out.println("加入LinkedList集合的时间"+(endc-startc)+"毫秒");

可能会有好奇的说,为啥这两个集合要创建100000这么大. Because现在牛逼的电脑,以及运行环境和其他偶然情况,在数据量小的时候可能根本体现不出差别来。

2**.用for循环分别遍历这两个集合。**

//用for遍历ArrayList集合:
				long estart = System.currentTimeMillis();
				for (int i = 0; i < csp.size(); i++) {
					csp.get(i);
				}
				long eend = System.currentTimeMillis();
				System.out.println("for遍历ArrayList集合的时间"+(eend-estart)+"毫秒");
				
		//用for遍历LinkedList集合:
				long eestart = System.currentTimeMillis();
				for (int i = 0; i < cspp.size(); i++) {
					cspp.get(i);
				}
				long eeend = System.currentTimeMillis();
				System.out.println("for遍历LinkedList集合的时间"+(eeend-eestart)+"毫秒");

耐心等待一下:

android 如何将List对象保存 java list存储对象_数据结构_02


哇,12280 / 5 上千倍的差距!

容易看出,在用for循环遍历的下,可以得出ArrayList的遍历快。前面提过它实现了 RandomAccess 标记性接口,用for循环遍历快。

3.用迭代器遍历两个集合。
前面提过List接口实现了 Iterator 接口。可以的到对应的迭代器,从而遍历集合。

//用迭代器遍历ArrayList集合:
				long estartp = System.currentTimeMillis();
				 for (Iterator<Integer> i=csp.iterator(); i.hasNext(); ){
			         i.next();
				 }
				long eendp = System.currentTimeMillis();
				System.out.println("用遍历迭代器集合ArrayList的时间"+(eendp-estartp)+"毫秒");
				
		//用迭代器遍历LinkedList集合://迭代过程中允许从中删除元素
				long estartpp = System.currentTimeMillis();
				 for (Iterator<Integer> i=cspp.iterator(); i.hasNext(); ){
			         i.next();
				 }
				long eendpp = System.currentTimeMillis();
				System.out.println("用遍历迭代器集合LinkedList的时间"+(eendpp-estartpp)+"毫秒");

结果如下:

android 如何将List对象保存 java list存储对象_android 如何将List对象保存_03


奇迹又发生的了。两个的时间居然!居然!

这又是为何:了解一下,迭代器的运行原理吧。

把访问逻辑从不同类型的集合类中抽取出来,从而避免向外部暴露集合的内部结构。是通过顺序反访问的方式来遍历集合中的元素。而且用迭代器遍历ArrayList和LinkedList的方式是一样的所以时间也就是几乎一样的了。

然后,将LinkedList用for循环和迭代器纵向比较一下

android 如何将List对象保存 java list存储对象_链表_04


结果很明显,链表更适合顺序访问。

4.两集合删除的时间比较。

// 删除ArrayList集合元素:
		long estart = System.currentTimeMillis();
		for (int i = 0; i < 1000; i++) {
			csp.remove(i);
		}
		long eend = System.currentTimeMillis();
		System.out.println("删除ArrayList集合中1000个元素的时间" + (eend - estart) + "毫秒");

		// 删除LinkedList集合元素:
		long eestart = System.currentTimeMillis();
		for (int i = 0; i < 1000; i++) {
			cspp.remove(i);
		}
		long eeend = System.currentTimeMillis();
		System.out.println("删除LinkedList集合中1000个元素的时间" + (eeend - eestart) + "毫秒");

结果:

android 如何将List对象保存 java list存储对象_数据结构_05


在ArrayList集合中元素的删除,需要数组后面的元素向前移动。而链表则不需要移动,所以LinkedList所需要的时间更少。

总结一下:

ArrayList 支持随机访问,用for循环遍历快,插入,删除元素慢,因为需要元素的移动。

LinkedList 支持顺序访问,用迭代器遍历较好,for遍历慢,插入,删除元素快,不需要元素的移动。

望大佬指正不妥之处!