Java中常常会用到迭代列表数据的状况,本文针对几种经常使用的写法进行效率比较。虽然网上已经有了相似的文章,可是对他们的结论并不认同。java
常见的实现方法:
1.for循环:数组
- for(int i = 0; i < list.size(); i++)
- for(int i = 0, size = list.size(); i < size; i++)
通常人都会认为第二种写法效率高。
函数
2.foreach:测试
这是一种简洁的写法,只能对列表进行读取,没法修改。spa
3.while:.net
- int size = list.size();
- while(size-- > 0)
4.迭代:对象
- Object iter = list.iterator();
- while(iter.hasNext()) {
- iter.next();
- }
测试代码:
针对以上几种方法编写的测试代码。blog
- public static void main(String[] args) {
- List<Integer> list = new ArrayList<Integer>();
-
- int runTime = 1000;
- for (int i = 0; i < 1000 * 1000; i++) {
- list.add(i);
- }
- int size = list.size();
- long currTime = System.currentTimeMillis();
-
- for(int j = 0; j < runTime; j++) {
- for (int i = 0; i < size; i++) {
- list.get(i);
- }
- }
- long time1 = System.currentTimeMillis();
-
-
- for(int j = 0; j < runTime; j++) {
- for (Integer integer : list) {
- }
- }
- long time2 = System.currentTimeMillis();
-
- for(int j = 0; j < runTime; j++) {
-
- int i = 0 ;
- while(i < size){
- list.get(i++);
- }
- }
- long time3 = System.currentTimeMillis();
-
- for(int j = 0; j < runTime; j++) {
- for (int i = 0; i < list.size(); i++) {
- list.get(i);
- }
- }
- long time4 = System.currentTimeMillis();
-
- for(int j = 0; j < runTime; j++) {
- Iterator<Integer> iter = list.iterator();
- while(iter.hasNext()) {
- iter.next();
- }
- }
- long time5 = System.currentTimeMillis();
-
- long time = time1 - currTime ;
- System.out.print("use for:" + time);
- time = time2 - time1;
- System.out.print("\tuse foreach:" + time);
- time = time3 - time2;
- System.out.print("\tuse while:" + time);
- time = time4 - time3;
- System.out.print("\tuse for2:" + time);
- time = time5 - time4;
- System.out.print("\tuse iterator:" + time);
- System.out.println();
- }
输出结果(JDK1.6):
1.ip
use for:8695 use foreach:17091 use while:6867 use for2:7741 use iterator:14144get
2.
use for:8432 use foreach:18126 use while:6905 use for2:7893 use iterator:13976
3.
use for:8584 use foreach:17177 use while:6875 use for2:7707 use iterator:14345
结论:
1.针对列表的 foreach的效率是最低:
耗时是普通for循环的2倍以上。我的理解它的实现应该和iterator类似。
2. list.size()的开销很小:
list.size()次数多少对效率基本没有影响。查看ArrayList的实现就会发现,size()方法的只是返回了对象内的长度属性,并无其它计算,因此只存在函数调用的开销。
对数组的测试:
将代码中的列表list换作数组再进行测试(iterator不适用),发现耗时基本为0。说明:
3. 列表的get()方法开销很多
应该主要是检测数据合法性时产生的。
将执行次数增长100万倍,这时能够看出结果基本相等,并无明显的差别。说明:
4. 数组length也没有开销
可见数组长度并非每次执行的时候都要计算的。联想一下Java建立数组的时候要求必须指定数组的长度,编译处理的时候显然没有把这个值抛弃掉。
网上有一篇相似的文章,它竟然得出了一个foreach执行效率最高的结论。看一下它的测试代码就会发现一个要命的问题,它竟然在执行每次循环的时候调用了System.out.print()方法将数组内容输出,难道他不知道这个操做耗时很是大吗,这样计算出的结果有什么用处呢。