基本上每次面试都会被问到这个问题,我的回答基本都是foreach性能比for循环好,可是真的是这样么?
常用的遍历类一般是ArrayList、LinkedList、数组,现在实际测试一下。
ArrayList
分别测试一千、一万、十万、百万条数据
测试代码:
public static void main (String[] args) {
List<String> list = new ArrayList<>();
int k = 0;
while (k <= 1000000) {
list.add(String.valueOf(k));
k++;
}
int first = 0;
int second = 0;
for(int m=0; m < 100; m++) {
long start = System.currentTimeMillis();
int size = list.size();
for (int i = 0; i < size; i++) {
System.out.println(list.get(i));
}
first += System.currentTimeMillis() - start;
long startTwo = System.currentTimeMillis();
for (String i : list) {
System.out.println(i);
}
second += System.currentTimeMillis() - startTwo;
}
BigDecimal divior = new BigDecimal(100);
System.out.println("for总耗时" + first + "毫秒");
System.out.println("for平均耗时" + new BigDecimal(first).divide(divior,2, BigDecimal.ROUND_HALF_UP) + "毫秒");
System.out.println("foreach总耗时" + second + "毫秒");
System.out.println("foreach平均总耗时" + new BigDecimal(second).divide(divior,2, BigDecimal.ROUND_HALF_UP) + "毫秒");
}
测试结果:
条数 | 循环类别 | 执行次数 | 总耗时 | 平均耗时 |
---|---|---|---|---|
一千 | for | 100 | 1163ms | 11.63ms |
一千 | foreach | 100 | 1001ms | 10.01ms |
一万 | for | 100 | 10749ms | 107.49ms |
一万 | foreach | 100 | 10548ms | 105.48ms |
十万 | for | 100 | 121296ms | 1212.96ms |
十万 | foreach | 100 | 119647ms | 1196.47ms |
百万 | for | 100 | 1202435ms | 12024.35ms |
百万 | foreach | 100 | 1200809ms | 12008.09ms |
从上面表格可以看出,再遍历ArrayList的时候,for循环与foreach循环性能几乎没有差别(有一点差别,应该是循环体代码造成的)。
所以,可以认为遍历ArrayList两种遍历方式性能是一样的,foreach循环性能并不优于for循环。
数组
测试代码:
public static void main (String[] args) {
String[] list = new String[1000];
int k = 0;
while (k < 1000) {
list[k] = String.valueOf(k);
k++;
}
int first = 0;
int second = 0;
for(int m=0; m < 100; m++) {
long start = System.currentTimeMillis();
int size = list.length;
for (int i = 0; i < size; i++) {
System.out.println(list[i]);
}
first += System.currentTimeMillis() - start;
long startTwo = System.currentTimeMillis();
for (String i : list) {
System.out.println(i);
}
second += System.currentTimeMillis() - startTwo;
}
BigDecimal divior = new BigDecimal(100);
System.out.println("for总耗时" + first + "毫秒");
System.out.println("for平均耗时" + new BigDecimal(first).divide(divior,2, BigDecimal.ROUND_HALF_UP) + "毫秒");
System.out.println("foreach总耗时" + second + "毫秒");
System.out.println("foreach平均总耗时" + new BigDecimal(second).divide(divior,2, BigDecimal.ROUND_HALF_UP) + "毫秒");
}
测试结果:
条数 | 循环类别 | 执行次数 | 总耗时 | 平均耗时 |
---|---|---|---|---|
一千 | for | 100 | 1134ms | 11.34ms |
一千 | foreach | 100 | 1057ms | 10.57ms |
一万 | for | 100 | 8957ms | 89.57ms |
一万 | foreach | 100 | 9185ms | 91.85ms |
十万 | for | 100 | 86097ms | 860.97ms |
十万 | foreach | 100 | 88355ms | 883.55ms |
百万 | for | 100 | 850238ms | 8502.38ms |
百万 | foreach | 100 | 862321ms | 8623.21ms |
和ArrayList一样,for循环与foreach循环性能几乎没有差别。
所以遍历数组,两种遍历方式都可以。
LinkedList
测试代码:
public static void main (String[] args) {
List<String> list = new LinkedList<>();
int k = 0;
while (k < 1000) {
list.add(String.valueOf(k));
k++;
}
int first = 0;
int second = 0;
for(int m=0; m < 50; m++) {
long start = System.currentTimeMillis();
int size = list.size();
for (int i = 0; i < size; i++) {
System.out.println(list.get(i));
}
first += System.currentTimeMillis() - start;
long startTwo = System.currentTimeMillis();
for (String i : list) {
System.out.println(i);
}
second += System.currentTimeMillis() - startTwo;
}
BigDecimal divior = new BigDecimal(100);
System.out.println("for总耗时" + first + "毫秒");
System.out.println("for平均耗时" + new BigDecimal(first).divide(divior,2, BigDecimal.ROUND_HALF_UP) + "毫秒");
System.out.println("foreach总耗时" + second + "毫秒");
System.out.println("foreach平均总耗时" + new BigDecimal(second).divide(divior,2, BigDecimal.ROUND_HALF_UP) + "毫秒");
}
测试结果:
条数 | 循环类别 | 执行次数 | 总耗时 | 平均耗时 |
---|---|---|---|---|
一千 | for | 50 | 499ms | 9.98ms |
一千 | foreach | 50 | 585ms | 11.70ms |
一万 | for | 100 | 9099ms | 181.98ms |
一万 | foreach | 50 | 5096ms | 101.92ms |
十万 | for | 100 | 477762ms | 9555.24ms |
十万 | foreach | 50 | 49588ms | 991.76ms |
数据对比非常明显,当数据量越来越大的时候,for循环已经不适用于linkedList的遍历了,而foreach还能保持很好的性能。
此时,可以说foreach性能比for好。
总结
1、foreach在遍历LinkedList的时候,性能是明显优于for;
2、在遍历数组和ArrayList的时候,两者没有明显区别;