最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

為什么在foreach循環(huán)中JAVA集合不能添加或刪除元素

 更新時(shí)間:2021年06月11日 17:04:46   作者:penriver  
今天給大家?guī)?lái)的文章是關(guān)于Java的相關(guān)知識(shí),文章圍繞著為什么在foreach循環(huán)中JAVA集合不能添加或刪除元素展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下

1. 編碼強(qiáng)制規(guī)約

在《阿里巴巴Java開(kāi)發(fā)手冊(cè)》中,針對(duì)集合操作,有一項(xiàng)規(guī)定,如下:

【強(qiáng)制】不要在 foreach 循環(huán)里進(jìn)行元素的 remove/add 操作。remove 元素請(qǐng)使用 Iterator方式,如果并發(fā)操作,需要對(duì) Iterator 對(duì)象加鎖。

public class SimpleTest {
    public static void main(String[] args) {
        List<String> list = Lists.newArrayList();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
 
        //正例
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String item = iterator.next();
            if ("1".equalsIgnoreCase(item)) {
                iterator.remove();
            }
        }
 
        //反例
        for (String item : list) {
            if ("2".equals(item)) {
                list.remove(item);
            }
        }
    }
}

2. 原因分析

在循環(huán)或迭代時(shí),會(huì)首先創(chuàng)建一個(gè)迭代實(shí)例,這個(gè)迭代實(shí)例的expectedModCount 賦值為集合的modCount.   

每當(dāng)?shù)魇?#12132; hashNext() / next() 遍歷下⼀個(gè)元素之前,都會(huì)檢測(cè) modCount 變量與expectedModCount 值是否相等,相等的話就返回遍歷;否則就拋出異常【ConcurrentModificationException】,終⽌遍歷

如果在循環(huán)中添加或刪除元素,是直接調(diào)用集合的add,remove方法【導(dǎo)致了modCount增加或減少】,但這些方法不會(huì)修改迭代實(shí)例中的expectedModCount,導(dǎo)致在迭代實(shí)例中expectedModCount 與 modCount的值不相等,拋出ConcurrentModificationException異常

但迭代器中的remove,add方法,會(huì)在調(diào)用集合的remove,add方法后,將expectedModCount 重新賦值為modCount,所以在迭代器中增加、刪除元素是可以正常運(yùn)行的。

可以參考ArrayList中的內(nèi)部私有類(lèi)Itr、ListItr的源碼

public Iterator<E> iterator() {
        return new Itr();
    }
 
/**
     * An optimized version of AbstractList.Itr
     */
    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;
 
        Itr() {}
 
        //刪除了一些代碼
 
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();
 
            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
 
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
 
  }
   public E remove(int index) {
        rangeCheck(index);
 
        modCount++;
        E oldValue = elementData(index);
 
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
 
        return oldValue;
    }

3. 相關(guān)知識(shí)介紹

3.1. 什么是快速失敗(fail-fast)?

快速失敗(fail-fast) 是 Java 集合的⼀種錯(cuò)誤檢測(cè)機(jī)制。在使⽤迭代器對(duì)集合進(jìn)⾏遍歷的時(shí)候,在多線程下操作⾮安全失敗(fail-safe)的集合類(lèi)可能就會(huì)觸發(fā) fail-fast 機(jī)制,導(dǎo)致拋出ConcurrentModificationException 異常。 

另外,在單線程下,如果在遍歷過(guò)程中對(duì)集合對(duì)象的內(nèi)容進(jìn)⾏了修改的話也會(huì)觸發(fā) fail-fast 機(jī)制。

舉個(gè)例⼦:多線程下,如果線程 1 正在對(duì)集合進(jìn)⾏遍歷,此時(shí)線程 2 對(duì)集合進(jìn)⾏修改(增加、刪除、修改),或者線程 1 在遍歷過(guò)程中對(duì)集合進(jìn)⾏修改,都會(huì)導(dǎo)致線程 1 拋出ConcurrentModificationException 異常。

3.2. 什么是安全失敗(fail-safe)呢?

采⽤安全失敗機(jī)制的集合容器,在遍歷時(shí)不是直接在集合內(nèi)容上訪問(wèn)的,⽽是先復(fù)制原有集合內(nèi)容,在拷⻉的集合上進(jìn)⾏遍歷。所以,在遍歷過(guò)程中對(duì)原集合所作的修改并不能被迭代器檢測(cè)到,故不會(huì)拋ConcurrentModificationException 異常。

到此這篇關(guān)于為什么在foreach循環(huán)中JAVA集合不能添加或刪除元素的文章就介紹到這了,更多相關(guān)JAVA集合添加或刪除元素內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringMVC MethodArgumentResolver的作用與實(shí)現(xiàn)

    SpringMVC MethodArgumentResolver的作用與實(shí)現(xiàn)

    這篇文章主要介紹了SpringMVC MethodArgumentResolver的作用與實(shí)現(xiàn),MethodArgumentResolver采用一種策略模式,在Handler的方法被調(diào)用前,Spring MVC會(huì)自動(dòng)將HTTP請(qǐng)求中的參數(shù)轉(zhuǎn)換成方法參數(shù)
    2023-04-04
  • Ribbon負(fù)載均衡算法原理與使用介紹

    Ribbon負(fù)載均衡算法原理與使用介紹

    在微服務(wù)中,對(duì)服務(wù)進(jìn)行拆分之后,必然會(huì)帶來(lái)微服務(wù)之間的通信需求,而每個(gè)微服務(wù)為了保證高可用性,又會(huì)去部署集群,那么面對(duì)一個(gè)集群微服務(wù)進(jìn)行通信的時(shí)候,如何進(jìn)行負(fù)載均衡也是必然需要考慮的問(wèn)題
    2022-09-09
  • 一文詳解RabbitMQ如何保證消息可靠性

    一文詳解RabbitMQ如何保證消息可靠性

    這篇文章將詳細(xì)介紹RabbitMQ的消息可靠性機(jī)制,如消息丟失,消息重復(fù)性消費(fèi),消息積壓等問(wèn)題,具有一定的參考價(jià)值,需要的朋友可以參考下
    2023-07-07
  • Java并發(fā)編程示例(七):守護(hù)線程的創(chuàng)建和運(yùn)行

    Java并發(fā)編程示例(七):守護(hù)線程的創(chuàng)建和運(yùn)行

    這篇文章主要介紹了Java并發(fā)編程示例(七):守護(hù)線程的創(chuàng)建和運(yùn)行,在本節(jié)示例中,我們將創(chuàng)建兩個(gè)線程,一個(gè)是普通線程,向隊(duì)列中寫(xiě)入事件,另外一個(gè)是守護(hù)線程,清除隊(duì)列中的事件,需要的朋友可以參考下
    2014-12-12
  • 一文搞懂SpringBoot如何利用@Async實(shí)現(xiàn)異步調(diào)用

    一文搞懂SpringBoot如何利用@Async實(shí)現(xiàn)異步調(diào)用

    異步調(diào)用幾乎是處理高并發(fā),解決性能問(wèn)題常用的手段,如何開(kāi)啟異步調(diào)用?SpringBoot中提供了非常簡(jiǎn)單的方式,就是一個(gè)注解@Async。今天我們重新認(rèn)識(shí)一下@Async,以及注意事項(xiàng)
    2022-09-09
  • springboot打包jar和war包的教程圖解

    springboot打包jar和war包的教程圖解

    這篇文章主要介紹了springboot打包jar和war包的方法,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • 基于SpringBoot實(shí)現(xiàn)防盜鏈功能

    基于SpringBoot實(shí)現(xiàn)防盜鏈功能

    防盜鏈?zhǔn)潜Wo(hù)資源服務(wù)器的常用方法,旨在防止未經(jīng)授權(quán)的外部鏈接直接訪問(wèn)服務(wù)器上的資源,如圖片、音頻和視頻文件,在本文中,我們將探討防盜鏈的概念和原理,并結(jié)合 Spring Boot 提供一個(gè)完整的可運(yùn)行示例,需要的朋友可以參考下
    2024-12-12
  • springboot3.X 無(wú)法解析parameter參數(shù)問(wèn)題分析

    springboot3.X 無(wú)法解析parameter參數(shù)問(wèn)題分析

    本文介紹了Spring Boot 3.2.1版本中調(diào)用接口時(shí)出現(xiàn)的參數(shù)解析問(wèn)題,該錯(cuò)誤是由Spring新版本加強(qiáng)的錯(cuò)誤校驗(yàn)和報(bào)錯(cuò)提示導(dǎo)致的,在Spring 6.1之后,官方要求URL中的傳參必須使用`@PathVariable`聲明用于接收的變量,而不能省略`@RequestParam`注解,感興趣的朋友一起看看吧
    2025-03-03
  • dubbo服務(wù)鏈路跟蹤方式

    dubbo服務(wù)鏈路跟蹤方式

    這篇文章主要介紹了dubbo服務(wù)鏈路跟蹤方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • list轉(zhuǎn)tree和list中查找某節(jié)點(diǎn)下的所有數(shù)據(jù)操作

    list轉(zhuǎn)tree和list中查找某節(jié)點(diǎn)下的所有數(shù)據(jù)操作

    這篇文章主要介紹了list轉(zhuǎn)tree和list中查找某節(jié)點(diǎn)下的所有數(shù)據(jù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09

最新評(píng)論

申扎县| 霍邱县| 梨树县| 凉山| 剑河县| 塔城市| 湟源县| 湟源县| 临颍县| 宁德市| 凤城市| 固始县| 河北区| 白水县| 万盛区| 阜城县| 和政县| 盖州市| 普格县| 凌云县| 沙河市| 西和县| 喀什市| 屯留县| 德惠市| 甘德县| 桐城市| 来凤县| 攀枝花市| 弥勒县| 忻城县| 皋兰县| 嘉义县| 吐鲁番市| 大同市| 互助| 广丰县| 三原县| 岚皋县| 平果县| 吉木萨尔县|