1- # List的循环性能
1+ # List遍历性能比较
2+
3+ List遍历性能比较,看看各种方式遍历的性能差别。
4+
5+
6+
7+ ## 结构差别:
28
39我们常用的List有两种,ArrayList和LinkedList,但由于内部存储结构的不同,使用不同的遍历方法引起的效果则是千差万别的。
410
5- List | 存储结构 | 特点
6- ---|---|---
7- ArrayList | 数组结构 | 可以根据下标直接取值
8- LinkedList | 链表结构 | 如果需要寻找某一个下标的数值必须从头遍历
11+ | List | 存储结构 | 特点 |
12+ | ---------- | ---- | --------------------- |
13+ | ArrayList | 数组结构 | 可以根据下标直接取值。 |
14+ | LinkedList | 链表结构 | 如果需要寻找某一个下标的数值必须从头遍历。 |
15+
16+
17+
18+ ## 常见做法:
919
1020我们在遍历List的时候可能会这样做:
1121
@@ -20,38 +30,102 @@ public void loopList(List<Integer> lists) {
2030
2131这种做法很直观,乍一看并没有什么问题,但是仔细分析一下就能知道,在这种情况下使用ArrayList与LinkedList性能是完全不同的。
2232
23- List | 循环时间复杂度 | get(i)时间复杂度 | 总时间复杂度
24- ---| :---:| :---:| :---:
25- ArrayList | O(n) | O(1) | O(n)
26- LinkedList | O(n) | O(n) | O(n<sup >2</sup >)
33+ | List | 循环时间复杂度 | get(i)时间复杂度 | 总时间复杂度 |
34+ | ---------- | :-----: | :---------: | :--------------: |
35+ | ArrayList | O(n) | O(1) | O(n) |
36+ | LinkedList | O(n) | O(n) | O(n<sup >2</sup >) |
2737
2838从时间复杂度上两者就直接差了一个数量级,可能这样说不明显,为了直观的表示,下面用代码测试处理10000条数据效率:
2939
30- 测试代码:
31- ```
40+ ### 性能测试:
41+
42+ 创建数据:
43+
44+ ``` java
3245ArrayList<Integer > arrayList = new ArrayList<> ();
33- LinkedList<Integer> linkedList = new LinkedList<>();
34- for (int i=0; i<10000; i++){
35- arrayList.add(i);
36- linkedList.add(i);
37- }
46+ LinkedList<Integer > linkedList = new LinkedList<> ();
47+ for (int i= 0 ; i< 10000 ; i++ ){
48+ arrayList. add(i);
49+ linkedList. add(i);
50+ }
51+ ```
3852
39- long startTime1=System.currentTimeMillis(); //获取开始时间
40- loopList(arrayList);
41- long endTime1=System.currentTimeMillis(); //获取结束时间
42- Log.i(TAG, "ArrayList: "+(endTime1-startTime1)+"ms");
53+ 测试For循环用时:
4354
44- long startTime2=System.currentTimeMillis(); //获取开始时间
45- loopList(linkedList);
46- long endTime2=System.currentTimeMillis(); //获取结束时间
47- Log.i(TAG, "LinkedList:"+(endTime2-startTime2)+"ms");
55+ ``` java
56+ long startTime1= System . currentTimeMillis(); // 获取开始时间
57+ loopList(arrayList);
58+ iteratorList(arrayList);
59+ long endTime1= System . currentTimeMillis(); // 获取结束时间
60+ Log . i(" Time" , " For-ArrayList: " + (endTime1- startTime1)+ " ms" );
61+
62+ long startTime2= System . currentTimeMillis(); // 获取开始时间
63+ loopList(linkedList);
64+ long endTime2= System . currentTimeMillis(); // 获取结束时间
65+ Log . i(" Time" , " For-LinkedList:" + (endTime2- startTime2)+ " ms" );
4866```
4967
5068结果:
5169
5270``` shell
53- com.gcssloop.alltest I/MainActivity: ArrayList: 9ms
54- com.gcssloop.alltest I/MainActivity: LinkedList:709ms
71+ com.gcssloop.alltest I/Time: For- ArrayList: 20ms
72+ com.gcssloop.alltest I/Time: For- LinkedList:648ms
5573```
5674
75+ 可以看到,仅仅处理10000条数据两者所需时间简直不能比较,当数据量越来越大的时候,LinkedList必然会耗费更多时间。
76+
77+
78+
79+ ## 处理办法:
80+
81+ 我们在Java中有 迭代器(Iterator) 以及 For each循环,可以它们来替代掉这个原始的for循环。
82+
83+ ### 迭代器(Iterator):
84+
85+ ``` java
86+ public void iteratorList(List<Integer > lists){
87+ Iterator<Integer > it = lists. iterator();
88+ while (it. hasNext()){
89+ Integer integer = it. next();
90+ // TODO 处理数据
91+ }
92+ }
93+ ```
94+
95+ 测试代码与上面类似,就省略了。
96+
97+ 结果:
98+
99+ ``` shell
100+ com.gcssloop.alltest I/Time: Iterator-ArrayList: 4ms
101+ com.gcssloop.alltest I/Time: Iterator-LinkedList:6ms
102+ ```
103+
104+ ** 可以看到,两者最终耗费时间差不多而且均有大幅度提升。**
105+
106+
107+
108+ ### ForEach循环:
109+
110+ ``` java
111+ public void foreachList(List<Integer > lists){
112+ for (Integer i : lists) {
113+ // TODO 处理数据
114+ }
115+ }
116+ ```
117+
118+ 性能:
119+
120+ ``` shell
121+ com.gcssloop.alltest I/Time: ForEach-ArrayList: 5ms
122+ com.gcssloop.alltest I/Time: ForEach-LinkedList:5ms
123+ ```
124+
125+ 由于ForEach循环底层使用的也是迭代器,所以和迭代器性能类似。
126+
127+
128+
129+ ## 总结:
57130
131+ 推荐使用迭代器(Iterator)和ForEach遍历List,不要使用传统的For循环。
0 commit comments