Skip to content

Commit d624763

Browse files
committed
魔法-修复
1 parent f79bf34 commit d624763

File tree

1 file changed

+100
-26
lines changed

1 file changed

+100
-26
lines changed

ChaosCrystal/List循环性能.md

Lines changed: 100 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
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
3245
ArrayList<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

Comments
 (0)