日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

同时遍历多个dataframe_Java面试-容器的遍历

發布時間:2024/9/30 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 同时遍历多个dataframe_Java面试-容器的遍历 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

當我們用增強for循環遍歷非并發容器(HashMap、ArrayList等),如果修改其結構,會拋出異常ConcurrentModificationException,因此在阿里巴巴的Java規范中有說到:不要在foreach循環里進行元素的remove/add操作,remove元素請使用Iterator方式。,但是不是真的就不可以在增強for循環中修改結構嗎?其原理又是什么呢?

ConcurrentModificationException的含義

ConcurrentModificationException可以將其通俗的翻譯為并發修改異常,那么關注點就在并發和修改了。也許有些人會說,我只是在單線程中修改了,并沒有并發操作,但系統也拋了這樣的這樣的錯誤,這是為什么呢?別急,我們看看它的源碼解釋:

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

這個異常就是應用程序在做一些系統不允許的操作時拋出的。記住,只要是系統不允許的操作,就一定會拋錯的。

后面有一個值得注意的地方

Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.

fail-fast(快速失敗)并不能一定被保證,所以fail-fast操作會盡最大努力拋出該異常。既然是盡最大努力,因此無論是不是并發操作,只要是修改了,就一定會報錯。

既然如此,我們來看看for循環中遍歷修改容器結構,系統是如何知道的。

增for循環的原理

我們來看看增強for循環遍歷修改HashMap的代碼:

Map<String, String> hashMap = new HashMap<>(10);// 添加for (int i = 0; i < 10; i++) {hashMap.put("key" + i, "value" + i);}// 遍歷修改for (Entry<String, String> entry : hashMap.entrySet()) {String key = entry.getKey();hashMap.remove(key);}

這個時候,你如果運行的話,就會拋出ConcurrentModificationException,這個時候我們需要具體調試一下,發現遍歷第一次并刪除時沒有報錯,但第二次遍歷,在for循環的括號執行完后,就拋出了異常,這又是為什么呢?

讓我們反編譯一下class文件,看看究竟增強for循環做了什么:

Map<String, String> hashMap = new HashMap(10);for(int i = 0; i < 10; ++i) {hashMap.put("key" + i, "value" + i);}Iterator var5 = hashMap.entrySet().iterator();while(var5.hasNext()) {Entry<String, String> entry = (Entry)var5.next();String key = (String)entry.getKey();hashMap.remove(key);}

我們發現,雖然寫法上是增強for循環,但實際還是使用的while結合iterator進行遍歷,現在我們貼上這個代碼進行調試。

發現在第二次var5.next()處拋異常,接下來我們看看next方法究竟做了什么?

在HashMap的源碼中顯示:

final class EntryIterator extends HashIteratorimplements Iterator<Map.Entry<K,V>> {public final Map.Entry<K,V> next() { return nextNode(); }}final Node<K,V> nextNode() {Node<K,V>[] t;Node<K,V> e = next;if (modCount != expectedModCount)throw new ConcurrentModificationException();if (e == null)throw new NoSuchElementException();if ((next = (current = e).next) == null && (t = table) != null) {do {} while (index < t.length && (next = t[index++]) == null);}return e;}

我們注意到,nextNode()方法的第一個判斷就決定了是否拋出ConcurrentModificationException,那么modCount和expectedModCount究竟是什么呢?

modCount和expectedModCount

我們來看看modCount和expectedModCount的關系,當我們調用Iterator var5 = hashMap.entrySet().iterator();時,源代碼做了什么:

HashIterator() {expectedModCount = modCount;Node<K,V>[] t = table;current = next = null;index = 0;if (t != null && size > 0) { // advance to first entrydo {} while (index < t.length && (next = t[index++]) == null);}}

在一開始,就讓expectedModCount等于modCount,而當我們調用hashMap.remove(key);時,實際上修改了modCount的值:

final Node<K,V> removeNode(int hash, Object key, Object value,boolean matchValue, boolean movable) {Node<K,V>[] tab; Node<K,V> p; int n, index;if ((tab = table) != null && (n = tab.length) > 0 &&(p = tab[index = (n - 1) & hash]) != null) {Node<K,V> node = null, e; K k; V v;if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))node = p;else if ((e = p.next) != null) {if (p instanceof TreeNode)node = ((TreeNode<K,V>)p).getTreeNode(hash, key);else {do {if (e.hash == hash &&((k = e.key) == key ||(key != null && key.equals(k)))) {node = e;break;}p = e;} while ((e = e.next) != null);}}if (node != null && (!matchValue || (v = node.value) == value ||(value != null && value.equals(v)))) {if (node instanceof TreeNode)((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);else if (node == p)tab[index] = node.next;elsep.next = node.next;++modCount;--size;afterNodeRemoval(node);return node;}}return null;}

modCount增大1,那么,當我們下一次調用var5.next()時,自然就發現modCount和expectedModCount不等了。

修改結構的正確姿勢

使用增強for循環,本質還是在使用iterator,那為什么大家都在推介使用iterator.remove()呢?讓我們看看源代碼:

public final void remove() {Node<K,V> p = current;if (p == null)throw new IllegalStateException();if (modCount != expectedModCount)throw new ConcurrentModificationException();current = null;K key = p.key;removeNode(hash(key), key, null, false, false);expectedModCount = modCount;}

我們發現,這個remove方法雖然也調用了removeNode,但它在最后一步再次將modCount的值賦給expectedModCount,因此保證了下一次調用next()方法是不拋錯。

所以,我們要么就直接顯示地使用iterator,用它的remove方法移除對象。如果你實在想用增強for循環遍歷刪除,那么也只能在刪除一個后,立刻退出循環。但無論用哪種方法,當多個線程同時修改時,都會有出錯的可能性,因為你即時保證單個線程內的modCount和expectedModCount,但這個操作并不能保證原子性。

總結

如果在多線程環境下,我更推介使用ConcurrentHashMap,因為它沒有modCount和expectedModCount的概念,因此,即時你是使用增強for循環遍歷刪除,也不會出現問題。

有興趣的話可以關注我的公眾號或者頭條號,說不定會有意外的驚喜。

總結

以上是生活随笔為你收集整理的同时遍历多个dataframe_Java面试-容器的遍历的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 人人艹人人爱 | 风间由美一区 | 蜜桃久久久aaaa成人网一区 | 波多野结衣电车 | 国产理论视频在线观看 | 香蕉视频在线网站 | 欧美大黄 | 影音先锋丝袜制服 | 精品在线视频观看 | 国产乱国产乱老熟300部视频 | 伊人久久伊人 | 一区二区在线视频播放 | 狠狠撸在线观看 | 乱xxxxx普通话对白 | www.白虎| 男人天堂亚洲 | 亚洲天堂av免费在线观看 | 岳奶大又白下面又肥又黑水多 | 精品人妻一区二区三区含羞草 | 免费高清欧美大片在线观看 | www天天操 | 国产精品黄色片 | 亚州欧美在线 | 69av视频 | 免费观看一级一片 | 91久久久精品 | 欧美黄色免费看 | 向着小小的花蕾绽放 | 天天干天天操天天插 | 性猛╳xxx乱大交 | 国产日韩欧美成人 | 韩国av毛片 | 樱桃成人精品视频在线播放 | 伊人色综合久久天天 | xx久久| 1区2区视频 | 在线视频免费观看 | 国产福利不卡视频 | 国产女主播自拍 | 中文字幕在线播放不卡 | 免费av网址在线 | 国产精品久久久久久久蜜臀 | 99热99在线 | 久久窝窝 | 欧美精品一区二区三区三州 | 在线观看一区视频 | 亚洲欧洲国产日韩 | 中国黄色1级片 | 成人激情在线 | av影院在线播放 | 在线看成人 | 嫩草视屏| 假日游船 | 美女毛片视频 | 三级中文字幕在线 | 内射毛片内射国产夫妻 | 一级黄色性片 | 久久久精品 | 665566综合网 | 九色精品视频 | 精品成人久久 | 国产精品亚洲视频 | 不卡中文字幕在线观看 | 天天干夜夜艹 | 国产曰肥老太婆无遮挡 | 久久新视频 | 天天插插| 国产精品18p | 午夜视频福利 | 极品蜜桃臀肥臀-x88av | 福利一区在线 | 少妇激情一区二区三区视频 | 国内精品小视频 | 欧美三级大片 | 刘亦菲久久免费一区二区 | 91看片网页版 | 欧美伦乱| av大全网站 | 亚洲图片综合网 | 日韩a在线播放 | 日韩激情 | 亚洲第一色视频 | 绿帽视频 | 亚洲精品999| 国产区在线观看 | av手机网站| 麻豆网站在线免费观看 | 免费草逼网站 | 国产一级一区二区 | 中文字幕在线观看高清 | 波多野结衣不卡 | 蜜臀尤物一区二区三区直播 | 黄页网站免费在线观看 | 97干干干| 密桃成熟时在线观看 | 欧美巨鞭大战丰满少妇 | 51免费看成人啪啪片 | 国产亚洲AV无码成人网站在线 | 三年中国片在线高清观看 |