點贊功能使用MySQL還是Redis
這是最近面試時被問到的1道面試題,本篇博客對此問題進行總結(jié)分享。
1. 新手常犯的錯誤
可能很多新手(包括當年的我,哈哈)第一時間想到的寫法是下面這樣的:
public static void main(String[] args) { List<String> platformList = new ArrayList<>(); platformList.add("博客園"); platformList.add("CSDN"); platformList.add("掘金"); for (String platform : platformList) { if (platform.equals("博客園")) { platformList.remove(platform); } } System.out.println(platformList); }
然后滿懷信心的去運行,結(jié)果竟然拋
java.util.ConcurrentModificationException異常了,翻譯成中文就是:并發(fā)修改異常。
是不是很懵,心想這是為什么呢?
讓我們首先看下上面這段代碼生成的字節(jié)碼,如下所示:
由此可以看出,foreach循環(huán)在實際執(zhí)行時,其實使用的是Iterator,使用的核心方法是hasnext()和next()。
然后再來看下ArrayList類的Iterator是如何實現(xiàn)的呢?
可以看出,調(diào)用next()方法獲取下一個元素時,第一行代碼就是調(diào)用了checkForComodification();,而該方法的核心邏輯就是比較modCount和expectedModCount這2個變量的值。
在上面的例子中,剛開始modCount和expectedModCount的值都為3,所以第1次獲取元素"博客園"是沒問題的,但是當執(zhí)行完下面這行代碼時:
platformList.remove(platform);
modCount的值就被修改成了4。
所以在第2次獲取元素時,modCount和expectedModCount的值就不相等了,所以拋出了
java.util.ConcurrentModificationException異常。
既然不能使用foreach來實現(xiàn),那么我們該如何實現(xiàn)呢?
主要有以下3種方法:
- 使用Iterator的remove()方法
- 使用for循環(huán)正序遍歷
- 使用for循環(huán)倒序遍歷
接下來一一講解。
2. 使用Iterator的remove()方法
使用Iterator的remove()方法的實現(xiàn)方式如下所示:
public static void main(String[] args) { List<String> platformList = new ArrayList<>(); platformList.add("博客園"); platformList.add("CSDN"); platformList.add("掘金"); Iterator<String> iterator = platformList.iterator(); while (iterator.hasNext()) { String platform = iterator.next(); if (platform.equals("博客園")) { iterator.remove(); } } System.out.println(platformList); }
輸出結(jié)果為:
[CSDN, 掘金]
為什么使用iterator.remove();就可以呢?讓我們看下它的源碼:
可以看出,每次刪除一個元素,都會將modCount的值重新賦值給expectedModCount,這樣2個變量就相等了,不會觸發(fā)
java.util.ConcurrentModificationException異常。更多面試題,歡迎關(guān)注公眾號 Java面試題精選
3. 使用for循環(huán)正序遍歷
使用for循環(huán)正序遍歷的實現(xiàn)方式如下所示:
public static void main(String[] args) { List<String> platformList = new ArrayList<>(); platformList.add("博客園"); platformList.add("CSDN"); platformList.add("掘金"); for (int i = 0; i < platformList.size(); i++) { String item = platformList.get(i); if (item.equals("博客園")) { platformList.remove(i); i = i - 1; } } System.out.println(platformList); }
這種實現(xiàn)方式比較好理解,就是通過數(shù)組的下標來刪除,不過有個注意事項就是刪除元素后,要修正下下標的值:
i = i - 1;
為什么要修正下標的值呢?因為剛開始元素的下標是這樣的:
第1次循環(huán)將元素"博客園"刪除后,元素的下標變成了下面這樣:
第2次循環(huán)時i的值為1,也就是取到了元素”掘金“,這樣就導(dǎo)致元素"CSDN"被跳過檢查了,所以刪除完元素后,我們要修正下下標,這也是上面代碼中i = i - 1;的用途。更多面試問題可以關(guān)注微信訂閱號碼匠筆記回復(fù)面試獲取
4. 使用for循環(huán)倒序遍歷
使用for循環(huán)倒序遍歷的實現(xiàn)方式如下所示:
public static void main(String[] args) { List<String> platformList = new ArrayList<>(); platformList.add("博客園"); platformList.add("CSDN"); platformList.add("掘金"); for (int i = platformList.size() - 1; i >= 0; i--) { String item = platformList.get(i); if (item.equals("掘金")) { platformList.remove(i); } } System.out.println(platformList); }
這種實現(xiàn)方式和使用for循環(huán)正序遍歷類似,不過不用再修正下標,因為剛開始元素的下標是這樣的:
第1次循環(huán)將元素"掘金"刪除后,元素的下標變成了下面這樣:
第2次循環(huán)時i的值為1,也就是取到了元素”CSDN“,不會導(dǎo)致跳過元素,所以不需要修正下標。
所以在第2次獲取元素時,modCount和expectedModCount的值就不相等了,所以拋出了
java.util.ConcurrentModificationException異常。
既然不能使用foreach來實現(xiàn),那么我們該如何實現(xiàn)呢?
主要有以下3種方法:
- 使用Iterator的remove()方法
- 使用for循環(huán)正序遍歷
- 使用for循環(huán)倒序遍歷
接下來一一講解。
5. 使用Iterator的remove()方法
使用Iterator的remove()方法的實現(xiàn)方式如下所示:
public static void main(String[] args) { List<String> platformList = new ArrayList<>(); platformList.add("博客園"); platformList.add("CSDN"); platformList.add("掘金"); Iterator<String> iterator = platformList.iterator(); while (iterator.hasNext()) { String platform = iterator.next(); if (platform.equals("博客園")) { iterator.remove(); } } System.out.println(platformList); }
輸出結(jié)果為:
[CSDN, 掘金]
為什么使用iterator.remove();就可以呢?讓我們看下它的源碼:
可以看出,每次刪除一個元素,都會將modCount的值重新賦值給expectedModCount,這樣2個變量就相等了,不會觸發(fā)
java.util.ConcurrentModificationException異常。更多面試題,歡迎關(guān)注公眾號 Java面試題精選
6. 使用for循環(huán)正序遍歷
使用for循環(huán)正序遍歷的實現(xiàn)方式如下所示:
public static void main(String[] args) { List<String> platformList = new ArrayList<>(); platformList.add("博客園"); platformList.add("CSDN"); platformList.add("掘金"); for (int i = 0; i < platformList.size(); i++) { String item = platformList.get(i); if (item.equals("博客園")) { platformList.remove(i); i = i - 1; } } System.out.println(platformList); }
這種實現(xiàn)方式比較好理解,就是通過數(shù)組的下標來刪除,不過有個注意事項就是刪除元素后,要修正下下標的值:
i = i - 1;
為什么要修正下標的值呢?因為剛開始元素的下標是這樣的:
第1次循環(huán)將元素"博客園"刪除后,元素的下標變成了下面這樣:
第2次循環(huán)時i的值為1,也就是取到了元素”掘金“,這樣就導(dǎo)致元素"CSDN"被跳過檢查了,所以刪除完元素后,我們要修正下下標,這也是上面代碼中i = i - 1;的用途。更多面試問題可以關(guān)注微信訂閱號碼匠筆記回復(fù)面試獲取
7. 使用for循環(huán)倒序遍歷
使用for循環(huán)倒序遍歷的實現(xiàn)方式如下所示:
public static void main(String[] args) { List<String> platformList = new ArrayList<>(); platformList.add("博客園"); platformList.add("CSDN"); platformList.add("掘金"); for (int i = platformList.size() - 1; i >= 0; i--) { String item = platformList.get(i); if (item.equals("掘金")) { platformList.remove(i); } } System.out.println(platformList); }
這種實現(xiàn)方式和使用for循環(huán)正序遍歷類似,不過不用再修正下標,因為剛開始元素的下標是這樣的:
第1次循環(huán)將元素"掘金"刪除后,元素的下標變成了下面這樣:
第2次循環(huán)時i的值為1,也就是取到了元素”CSDN“,不會導(dǎo)致跳過元素,所以不需要修正下標。
到此這篇關(guān)于點贊功能使用MySQL還是Redis的文章就介紹到這了,更多相關(guān)MySQL\Redis點贊 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql error 1130 hy000:Host''localhost''解決方案
本文將詳細提供mysql error 1130 hy000:Host'localhost'解決方案,需要的朋友可以參考下2012-11-11Mysql實現(xiàn)null值排在最前/最后的方法示例
這篇文章主要給大家介紹了關(guān)于Mysql實現(xiàn)null值排在最前/最后的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02windows環(huán)境下Mysql中文亂碼問題解決方法
在搭建Mysql環(huán)境的時候遇到了中文亂碼問題,下面與大家分享下具體的解決方法,感興趣的朋友可以參考下哈,希望對大家有所幫助2013-06-06Mysql報錯1292:Incorrect datetime value for 
本文主要介紹了Mysql報錯1292:Incorrect datetime value for column create_time at row 1 解決方案,1292 是指插入或更新操作時,日期或時間值不正確引起的錯誤,下面就來介紹一下2024-02-02