先给结论,ArrayList数组结构的,插入和删除耗时长,get(index)耗时短。
LinkedList是链表结构的,插入和删除耗时短,get(index)耗时长。
常用的几种集合,ArrayList和LinkedList,看了一下这两种集合获取数据的效率。
public class TestList { @Test public void testLink() throws InterruptedException { LinkedList <Integer> link = new LinkedList<Integer>(); for(int i = 0;i<100000;i++){ link.add(i); } long time1 = System.currentTimeMillis(); //用link找坐标,花费时间大 //用link遍历Iterator数据,开销少于arrayList for(int i :link){ link.set(i,55); } long time2 = System.currentTimeMillis(); System.out.println(time2-time1); } @Test public void testArray() throws InterruptedException { ArrayList<Integer> link = new ArrayList<Integer>(); for(int i = 0;i<100000;i++){ link.add(i); } long time1 = System.currentTimeMillis(); for(int i :link){ link.set(i,55); } long time2 = System.currentTimeMillis(); System.out.println(time2-time1); } }
结果
12 4809
用Iterator迭代器,遍历LinkedList和ArrayList进行set/get 操作,很明显ArrayList的耗时要高很多。
同样的,用for循环读下标也是。
另一个例子
public class TestList { @Test public void testLink() throws InterruptedException { LinkedList <Integer> link = new LinkedList<Integer>(); long time1 = System.currentTimeMillis(); for(int i = 0;i<100000;i++){ link.add(i); } //用link找坐标,花费时间大 //用link遍历Iterator数据,开销少于arrayList long time2 = System.currentTimeMillis(); System.out.println(time2-time1); } @Test public void testArray() throws InterruptedException { ArrayList<Integer> link = new ArrayList<Integer>(); long time1 = System.currentTimeMillis(); for(int i = 0;i<100000;i++){ link.add(i); } long time2 = System.currentTimeMillis(); System.out.println(time2-time1); } }
结果
28 14
LinkedList在add时,耗时比ArrayList多一倍。
public class TestList { @Test public void testLink() throws InterruptedException { LinkedList <Integer> link = new LinkedList<Integer>(); for(int i = 0;i<100000;i++){ link.add(i); } long time1 = System.currentTimeMillis(); for(int i = 500;i<1000;i++){ link.remove(i); } //用link找坐标,花费时间大 //用link遍历Iterator数据,开销少于arrayList long time2 = System.currentTimeMillis(); System.out.println(time2-time1); } @Test public void testArray() throws InterruptedException { ArrayList<Integer> link = new ArrayList<Integer>(); for(int i = 0;i<100000;i++){ link.add(i); } long time1 = System.currentTimeMillis(); for(int i = 500;i<1000;i++){ link.remove(i); } long time2 = System.currentTimeMillis(); System.out.println(time2-time1); } }
结果
28 6
LinkedList在按照下标remove数据上,比ArrayList慢,这里和java-core上有些差异。
重新设置一下数据,让数据量较大,并且读取的数据较靠后,ArrayList的耗时就明显增加了。
public class TestList { @Test public void testLink() throws InterruptedException { LinkedList <Integer> link = new LinkedList<Integer>(); for(int i = 0;i<1000000;i++){ link.add(i); } Iterator<Integer>it = link.iterator(); long time1 = System.currentTimeMillis(); for(int i = 99000;i<99599;i++){ link.remove(i); } long time2 = System.currentTimeMillis(); System.out.println(time2-time1); } @Test public void testArray() throws InterruptedException { ArrayList<Integer> link = new ArrayList<Integer>(); for(int i = 0;i<1000000;i++){ link.add(i); } long time1 = System.currentTimeMillis(); for(int i = 99000;i<99599;i++){ link.remove(i); } long time2 = System.currentTimeMillis(); System.out.println(time2-time1); } }
结果:
291 898
这里摘抄一段java-core的解释,P568
数组和数组列表都有一个重大的缺陷,这就是从数组的中间位置删除一个元素要付出很大的代价,其原因是数组中处于被删除元素之后的所有元素都要向数组的前端移动,在数组中间的位置上插入一个元素也是如此。
从链表中间删除一个元素时一个很轻松的操作,即需要对被删除元素附近的节点更新一下即可。
但是链表与泛型集合之间有一个重要的区别,链表是一个有序集合(ordered collection),每个对象的位置十分重要。
这里又有一个疑问,P572说LinkedList下标读取object的效率不高,并且用for循环来读取下标的效率极低。事实上我测试的时候,ArrayList的get(i)效率更低,参见下面的代码。
public class TestList { @Test public void testLink() throws InterruptedException { LinkedList <Integer> link = new LinkedList<Integer>(); for(int i = 0;i<100000;i++){ link.add(i); } long time1 = System.currentTimeMillis(); //用link找坐标,花费时间大 //用link遍历Iterator数据,开销少于arrayList for(int i =0;i<10000;i++){ link.get(55); } long time2 = System.currentTimeMillis(); System.out.println(time2-time1); } @Test public void testArray() throws InterruptedException { ArrayList<Integer> link = new ArrayList<Integer>(); for(int i = 0;i<100000;i++){ link.add(i); } long time1 = System.currentTimeMillis(); for(int i =0;i<10000;i++){ link.get(55); } long time2 = System.currentTimeMillis(); System.out.println(time2-time1); } }
结果就不贴了,跟第一段代码的set的效率差异差不多大。
很难懂啊。。。。
搜了一下,应该是我的代码有问题。后来发现可能是因为我有两个test,test可能执行上有差异导致的?没研究清楚,分开执行结果是正确的,放在一起执行就是有问题。。。
参考https://www.cnblogs.com/skywang12345/p/3308900.html
修改了一下测试代码
package enums; import org.junit.Test; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * Created by user on 2019/7/2. */ public class TestList { @Test public void testLink() throws InterruptedException { LinkedList <Integer> linklist= new LinkedList<>(); ArrayList<Integer>arrayList = new ArrayList<>(); addList(linklist); addList(arrayList); getList(linklist); getList(arrayList); } public void getList(List list){ long startTime = System.currentTimeMillis(); for(int i =0;i<100000;i++){ list.get(i); } long endTime = System.currentTimeMillis(); System.out.println(endTime-startTime); } public void addList(List list){ long startTime = System.currentTimeMillis(); for(int i =0;i<100000;i++){ list.add(i); } long endTime = System.currentTimeMillis(); System.out.println(endTime-startTime); } }