ArrayList和JSONArray邊遍歷邊刪除到底該如何做
話題看起來有點(diǎn)老生了,但是加入JSONArray還是有很多新意
ArrayList
方式1:索引遍歷
? ? ? ? List<Integer> list = new ArrayList<>(); ? ? ? ? list.add(1); ? ? ? ? list.add(2); ? ? ? ? list.add(3456); ? ? ? ? list.add(3456); ? ? ? ? list.add(4); ? ? ? ? for(int i =0; i < list.size(); i++) { ? ? ? ? ? ? if(list.get(i) == 3456) { ? ? ? ? ? ? ? ? list.remove(i); ? ? ? ? ? ? } ? ? ? ? } ? ?? ? ? ? ? System.out.println(list);
沒有異常,有輸出結(jié)果[1, 2, 3456, 4],顯然是不對(duì)的,沒有把第二個(gè)3456刪除掉,問題比較明顯,就是每當(dāng)刪除一個(gè)條目底層就會(huì)有一次數(shù)據(jù)移動(dòng),即被刪除條目下一個(gè)索引數(shù)據(jù)占據(jù)了被刪除條目的位置,進(jìn)入到下一輪遍歷時(shí)恰好跳過了原來的下一個(gè)條目,就出現(xiàn)了上述的錯(cuò)誤現(xiàn)象。所以此種遍歷方式是不正確的。
方式2:for each遍歷
? ? ? ? List<Integer> list = new ArrayList<>(); ? ? ? ? list.add(1); ? ? ? ? list.add(2); ? ? ? ? list.add(3456); ? ? ? ? list.add(3456); ? ? ? ? list.add(4); ? ? ? ? /*for(int i =0; i < list.size(); i++) { ? ? ? ? ? ? if(list.get(i) == 3456) { ? ? ? ? ? ? ? ? list.remove(i); ? ? ? ? ? ? } ? ? ? ? }*/ ? ? ? ? for(Integer i: list) { ? ? ? ? ? ? if(i == 3456) { ? ? ? ? ? ? ? ? list.remove(i); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? System.out.println(list);
直接報(bào)出異常了:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
所以此種方式必然不行了。
方式3:迭代器遍歷
? ? ? ? List<Integer> list = new ArrayList<>(); ? ? ? ? list.add(1); ? ? ? ? list.add(2); ? ? ? ? list.add(3456); ? ? ? ? list.add(3456); ? ? ? ? list.add(4); ? ? ? ? Iterator<Integer> iterator = list.iterator(); ? ? ? ? while (iterator.hasNext()) { ? ? ? ? ? ? if(iterator.next() == 3456) { ? ? ? ? ? ? ? ? iterator.remove(); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? System.out.println(list);
運(yùn)行結(jié)果,完全正確[1, 2, 4]。這也是最推薦的方式。
當(dāng)然,除了第3種方式外,還有2種可以考慮的方式:
方式4. 不刪除,而是new一個(gè)新的list的將其中符合條件的添加到新的list,其實(shí)就實(shí)現(xiàn)了刪除,還是比較穩(wěn)妥的方式。
方式5.再一種就是對(duì)方式1的改進(jìn),一旦滿足條件執(zhí)行了刪除,就將index--,這樣也是可以實(shí)現(xiàn)的,只是很別扭。
JSONArray
首先,通過JSONArray的源代碼看下,其中與ArrayList的關(guān)聯(lián),進(jìn)入JSONArray類查看remove的代碼:
private final List<Object> list; ? ? public JSONArray() { ? ? ? ? this.list = new ArrayList(); ? ? } ? ? ?public boolean remove(Object o) { ? ? ? ? return this.list.remove(o); ? ? }
可以看到,底層就是調(diào)用的ArrayList的remove方法,那么據(jù)此可以推斷方式1,2也會(huì)各自存在同樣的問題。
那么方式3是不是就完全ok了?
JSONObject o1 = new JSONObject(); ? ? ? ? o1.put("key", 324); ? ? ? ? ? JSONObject o2 = new JSONObject(); ? ? ? ? o2.put("key", 325); ? ? ? ? ? JSONObject o3 = new JSONObject(); ? ? ? ? o3.put("key", 325); ? ? ? ? ? JSONObject o4 = new JSONObject(); ? ? ? ? o4.put("key", 327); ? ? ? ? ? JSONArray ja = ?new JSONArray(); ? ? ? ? ja.add(o1); ? ? ? ? ja.add(o2); ? ? ? ? ja.add(o3); ? ? ? ? ja.add(o4); ? ? ? ? ? Iterator<Object> o = ja.iterator(); ? ? ? ? while (o.hasNext()) { ? ? ? ? ? ? JSONObject jo = (JSONObject) o.next(); ? ? ? ? ? ? if(jo.getIntValue("key") == 325) { ? ? ? ? ? ? ? ? //ja.remove(jo); //不要用這種方式刪除,會(huì)報(bào)出ConcurrentModificationException ? ? ? ? ? ? ? ? o.remove(); //這種方式OK的 ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? ? System.out.println(ja);
運(yùn)行結(jié)果[{"key":324},{"key":327}]是完全正確的,只是這里有一點(diǎn)需要注意的是盡管循環(huán)用了iterator,那么刪除的時(shí)候也要用迭代器即o.remove()而不是ja.remove(jo),否則還是會(huì)有異常的。
此外,對(duì)應(yīng)的方式4,5在這里也是適用的,尤其是方式4,也是不錯(cuò)的方案。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用Spring的StopWatch實(shí)現(xiàn)代碼性能監(jiān)控的方法詳解
在開發(fā)過程中,偶爾還是需要分析代碼的執(zhí)行時(shí)間,Spring 框架提供了一個(gè)方便的工具類 StopWatch,本文將介紹 StopWatch 的基本用法,并通過示例演示如何在項(xiàng)目中使用 StopWatch 進(jìn)行代碼性能監(jiān)控2023-12-12Java實(shí)現(xiàn)5種負(fù)載均衡算法(小結(jié))
負(fù)載均衡是將客戶端請求訪問,通過提前約定好的規(guī)則轉(zhuǎn)發(fā)給各個(gè)server,本文主要介紹了Java實(shí)現(xiàn)5種負(fù)載均衡算法,具有一定的參考價(jià)值,感興趣的可以了解一下2022-06-06Java數(shù)組動(dòng)態(tài)增加容量過程解析
這篇文章主要介紹了Java數(shù)組動(dòng)態(tài)增加容量過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09java使用jdbc連接數(shù)據(jù)庫工具類和jdbc連接mysql數(shù)據(jù)示例
這篇文章主要介紹了java使用jdbc連接數(shù)據(jù)庫的工具類和使用jdbc連接mysql數(shù)據(jù)的示例,需要的朋友可以參考下2014-03-03AQS加鎖機(jī)制Synchronized相似點(diǎn)詳解
這篇文章主要為大家介紹了AQS加鎖機(jī)制Synchronized相似點(diǎn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Centos7安裝JDK1.8詳細(xì)過程實(shí)戰(zhàn)記錄
這篇文章主要給大家介紹了關(guān)于Centos7安裝JDK1.8的相關(guān)資料,文中通過圖文以及實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-09-09Maven中怎么手動(dòng)添加jar包到本地倉庫詳解(repository)
這篇文章主要給大家介紹了關(guān)于Maven中怎么手動(dòng)添加jar包到本地倉庫的相關(guān)資料,文中通過圖文以及實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-04-04Java實(shí)現(xiàn)文字滾動(dòng)廣告字幕效果
文字滾動(dòng)廣告字幕是一種常見的動(dòng)態(tài)文本展示效果,通常用于展示新聞、廣告或其他動(dòng)態(tài)信息,在本項(xiàng)目中,我們將使用Java的Swing庫來實(shí)現(xiàn)一個(gè)簡單的文字滾動(dòng)廣告字幕效果,通過定時(shí)更新文本的位置來模擬文字的滾動(dòng),需要的朋友可以參考下2025-02-02使用Runnable實(shí)現(xiàn)數(shù)據(jù)共享
這篇文章主要為大家詳細(xì)介紹了如何使用Runnable實(shí)現(xiàn)數(shù)據(jù)共享,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07