国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

由遍歷集合所聯想到的一些問題

2019-11-14 23:30:13
字體:
來源:轉載
供稿:網友
由遍歷集合所聯想到的一些問題

1、以下一段再平常不過的遍歷代碼,但是與我一樣,好多新手都會在這個地方出問題,例如

for(int i=0; i<list.size();i++)  // 執行;

之前我在剛工作的時候在這個地方犯錯,我們在自測的時候都沒問題。初始化數據之后給客戶演示時,突然蹦出個空指針異常NullPointerException。

于是我們通過debug發現,這個list為空,平常我們開發都會手工插入一些數據到表,自然不會報空,演示的時候數據表為空,自然就報錯了。改進:

for(int i=0; list!=null&&i<list.size(); i++)    //執行;

不會報錯了吧!

但是有經驗的開發人員會發現for循環,每次都會去對循環條件進行判斷,于是繼續改進

if(list!=null && !list.isEmpty())    for(int i=0; i<list.size(); i++)        // 執行;    

還有問題嗎

我們會發現循環還是每次都會去執行list.size();方法,list.size()方法也就是一句代碼return size;看似簡單的一句代碼,但是我們知道每次執行一個方法JVM都會為該方法申請一個棧幀,過程雖短,但是也是一項不小的開銷。于是繼續改進

if(list!=null && !list.isEmpty())    for(int i=0,len=list.size(); i<len; i++)        // 執行;    

這樣效率真的會高一些嗎,實驗是最好的答案

List<Integer> list = new ArrayList<Integer>();for(int i=0; i<30000000;i++)list.add(i);// 普通循環long t1 = System.currentTimeMillis();for(int j=0; j<100; j++)  for(int i=0; i<list.size(); i++) {    Integer it1 = list.get(i);  }System.out.PRintln(System.currentTimeMillis()-t1);// 改進lent1 = System.currentTimeMillis();for(int j=0; j<100; j++)  for(int i=0, len=list.size(); i<len; i++) {    Integer it2 = list.get(i);  }System.out.println(System.currentTimeMillis()-t1);// foreach方式遍歷t1 = System.currentTimeMillis();for(int j=0; j<100; j++)  for(Integer it4: list) {  }System.out.println(System.currentTimeMillis()-t1);結果普通for結果     22335使用len結果    14369使用foreach結果 29163

經過多次測試發現,普通for結果比len會多出三分之一左右,foreach效果比普通for會略差,而且經過多次測試發現一個有趣的現象,循環位于不同的位置,結果也會有所差距,貌似JVM對循環過的集合會進行優化,下一次再次循環這個集合,速度會有所加快,這個大家也可以去做一下實驗,集合過大的時候可能報堆溢出,可以通過修改。-Xms128M -Xmx512M

PS:以上遍歷方法不考慮多線程不會有什么問題,如果在多線程下遍歷將len提出來,就容易出錯了,因為len就獲取一次。

2、接下來考慮一個問題,多線程下需要同步遍歷某個公共集合,如何實現我們可能會想到用同步塊synchronized

synchronized(list) {     if(list!=null && !list.isEmpty())        for(int i=0,len=list.size(); i<len; i++)            執行;}    

這樣的代碼真的好嗎?我們可以想一想,多線程的情況下,你將公共的list一鎖,其他的線程想插入list刪除list只能干等著,更嚴重的是如果你在遍歷的時候還執行一些長時間的操作,例如關閉連接或者啟動監聽等等。于是我們就想如何能夠讓等待的時間盡量的短,我們完全可以先將集合克隆下來(至于深淺克隆根據具體情況而論),再去執行,當然如果循環執行時間很短,完全沒這個必要。

LifecycleListener[] interested = null;// 用克隆減少時間,因為如果一個一個去觸發事件響應,得使用大量時間,而又因為線程鎖的存在,使得其他線程必須繼續等待synchronized (listeners) {    interested = (LifecycleListener[])listeners.clone();}// 逐個觸發事件響應for(int i=0; i<interested.length; i++) {    interested[i].lifecycleEvent(event);}

為什么上面沒有使用len中間變量,因為數組的length并不會占用執行時間。


上一篇:Java基礎語法

下一篇:Struts2(一)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 萨嘎县| 商洛市| 大兴区| 灌南县| 方山县| 即墨市| 文安县| 四川省| 凤山市| 开平市| 吉安市| 大石桥市| 黄山市| 札达县| 洛川县| 万州区| 三台县| 左云县| 仁化县| 武邑县| 云林县| 蓬安县| 宁陕县| 视频| 潮州市| 瑞安市| 山阳县| 霍林郭勒市| 贺州市| 岢岚县| 应城市| 廊坊市| 克山县| 怀安县| 泽库县| 灵武市| 云浮市| 会昌县| 东宁县| 布拖县| 东阳市|