Java基礎(二)- 普通for迴圈、foreach效能比較

Keep_Stupid發表於2020-06-01

最近公司有一個需求,只展示被刪除資料的刪除時間,刪除時間對應updateTime欄位。測試環境對應表的資料量在40萬+,所以研究下普通for迴圈與foreach迴圈的效能比較。

以下測試用例中:集合使用的是ArrayList

測試用例1:

//對應的實體類:
class Country {
    private String name;
    private long area;
    private String updateTime;
    private int isDelete;//0:未刪除 1:刪除

    public Country(String name, long area, String updateTime, int isDelete) {
        this.name = name;
        this.area = area;
        this.updateTime = updateTime;
        this.isDelete = isDelete;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getArea() {
        return area;
    }

    public void setArea(long area) {
        this.area = area;
    }

    public String getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(String updateTime) {
        this.updateTime = updateTime;
    }

    public int getIsDelete() {
        return isDelete;
    }

    public void setIsDelete(int isDelete) {
        this.isDelete = isDelete;
    }
}

如果isDelete=0,那麼將updateTime置為null;

public class ForLoopTest {

    private List<Country> list = new ArrayList<>();

    public List<Country> listCountries(int count) {
        int isDelete = ((int) (10 * Math.random())) % 2;
        for (int i = 0; i < count; i++) {
            Country country = new Country(i + "", i, i + "", isDelete);
            list.add(country);
        }
        return list;
    }

    /**
     * @Description: 普通for迴圈
     */
    public long normalForLoop(List<Country> list) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getIsDelete() == 0) {
                list.get(i).setUpdateTime(null);
            }
        }
        long end = System.currentTimeMillis();
        return end - start;
    }

    /**
     * @Description: foreach迴圈
     */
    public long forEachLoop(List<Country> list) {
        long start = System.currentTimeMillis();
        for (Country country : list) {
           if(country.getIsDelete()==0){
               country.setUpdateTime(null);
           }
        }
        long end = System.currentTimeMillis();
        return end - start;

    }

    public void start() {
        List<Country> listCountries = listCountries(400000);
        long l = normalForLoop(listCountries);
        long l1 = forEachLoop(listCountries);
        System.out.println("普通for迴圈時間:" + l);
        System.out.println("foreach迴圈時間:" + l1);
    }

    public static void main(String[] args) {
        new ForLoopTest().start();
    }
}

40萬資料量測試結果:

 400萬資料量測試結果:

 

 發現兩者在業務中沒有很大的效能差異,後來查詢了多個部落格的測試用例,如下:

public class ForLoopTest {

    private List<Country> list = new ArrayList<>();

    public List<Country> listCountries(int count) {
        int isDelete = ((int) (10 * Math.random())) % 2;
        for (int i = 0; i < count; i++) {
            Country country = new Country(i + "", i, i + "", isDelete);
            list.add(country);
        }
        return list;
    }

    /**
     * @Description: 普通for迴圈
     */
    public long normalForLoop(List<Country> list) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < list.size(); i++) {
            list.get(i);
        }
        long end = System.currentTimeMillis();
        return end - start;
    }

    /**
     * @Description: foreach迴圈
     */
    public long forEachLoop(List<Country> list) {
        long start = System.currentTimeMillis();
        for (Country country : list) {

        }
        long end = System.currentTimeMillis();
        return end - start;

    }

    public void start() {
        List<Country> listCountries = listCountries(4000000);
        long l = normalForLoop(listCountries);
        long l1 = forEachLoop(listCountries);
        System.out.println("普通for迴圈時間:" + l);
        System.out.println("foreach迴圈時間:" + l1);
    }

    public static void main(String[] args) {
        new ForLoopTest().start();
    }
}

普通for迴圈中呼叫list的get方法,foreach迴圈的迴圈體中沒有程式碼;

40萬資料量測試結果如下:

400萬資料量測試結果如下:

 

 很明顯,普通for迴圈效能優於foreach迴圈

 

總結:基於列表為ArrayList,如果只考慮迴圈獲取list中的資料,那麼普通for迴圈優於foreach迴圈;如果在迴圈中需要進行邏輯判斷,那麼兩者效能相差不大

 

相關文章