新的未必比旧的好

95 阅读1分钟

「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战

老张是一位具有十年开发经验的资深程序员,最近在代码评审会上他的代码收到了实习生小李的质疑。事情是这样的,老张的代码中存在一个循环,这个循环每次都会向数组中写入一个值,然后循环遍历这个数组每次循环就累加 1 最后输出累加结果。简化后的代码如下:

private static final int size=999999999;
private static List<String> nums=new ArrayList<>();
public static void init(){		
    for(int i=0;i<size;i++) {
        nums.add(""+i);
    }
}
public static void index() {
    int count=0;
    for(int i=0;i<nums.size();i++) {
        count++;
    }
    System.out.println(count);
}

对于这段代码小李认为项目所用的 JDK 已经是 1.5 以上版本了,就不该使用索引的方式遍历,因为很多人都推荐使用 foreach 进行遍历并且它对算法做了优化性能更好。这番说辞立刻被老张怼了回去,并给出了一段代码分别用来测试 foreach 、Iterator 和 for 的效率。

public static void main(String[] args) {
    init();
    long startTime=System.currentTimeMillis();
    foreach();
    System.out.println(System.currentTimeMillis()-startTime);
    startTime=System.currentTimeMillis();
    iterator();
    System.out.println(System.currentTimeMillis()-startTime);
    startTime=System.currentTimeMillis();
    index();
    System.out.println(System.currentTimeMillis()-startTime);		
}
public static void foreach() {	
    int count=0;
    for(String str:nums) {
        count++;
    }
    System.out.println(count);
}
public static void iterator() {
    Iterator<String> it=nums.iterator();
    int count=0;
    while(it.hasNext()) {
        it.next();
        count++;
    }
    System.out.println(count);
}

运行代码并测试一万、一百万、一亿三个不同级别,耗时(毫秒)如下:

级别foreachIteratorindex
一万211
一百万14108
一亿60137

小李看到这个结果很是震惊,老张说:虽然 foreach 循环耗时很大,但是它在语法简洁和预防 BUG 方面有很大的优势,并且性能只比 for 循环稍微差了点,在对时间不是很在意的情况下可以使用 foreach 循环,但是如果有如下三种情况即使不在意时间也不能使用:

  1. 平行迭代:如果要同时遍历多个集合,需要多个集合的所以同步移动;
  2. 过滤:遍历集合的同时需要显示的使用迭代器删除指定元素;
  3. 转换:如果需要遍历列表或者数组,并在遍历的过程中使用列表迭代器或数字索引替换元素的值。