最近公司有一個需求,只展示被刪除資料的刪除時間,刪除時間對應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迴圈;如果在迴圈中需要進行邏輯判斷,那麼兩者效能相差不大