欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中如何正確遍歷刪除List中的元素

 更新時(shí)間:2023年11月21日 11:21:07   作者:程序員子龍  
刪除List中元素這個(gè)場(chǎng)景很場(chǎng)景,很多人可能直接在循環(huán)中直接去刪除元素,這樣做對(duì)嗎?下面小編就來(lái)和大家一起討論如何正確遍歷刪除List中的元素,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下

for循環(huán)索引刪除

刪除長(zhǎng)度為4的字符串元素。

    List<String> list = new ArrayList<String>();
    list.add("AA");
    list.add("BBB");
    list.add("CCCC");
    list.add("DDDD");
    list.add("EEE");
?
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i).length() == 4) {
            list.remove(i);
        }
    }
    System.out.println(list);
}

實(shí)際上輸出結(jié)果:

[AA, BBB, DDDD, EEE]

DDDD 竟然沒(méi)有刪掉!

原因是:刪除某個(gè)元素后,list的大小size發(fā)生了變化,而list的索引也在變化,索引為i的元素刪除后,后邊元素的索引自動(dòng)向前補(bǔ)位,即原來(lái)索引為i+1的元素,變?yōu)榱怂饕秊?code>i的元素,但是下一次循環(huán)取的索引是i+1,此時(shí)你以為取到的是原來(lái)索引為i+1的元素,其實(shí)取到是原來(lái)索引為i+2的元素,所以會(huì)導(dǎo)致你在遍歷的時(shí)候漏掉某些元素。

比如當(dāng)你刪除第1個(gè)元素后,繼續(xù)根據(jù)索引訪問(wèn)第2個(gè)元素時(shí),因?yàn)閯h除的關(guān)系后面的元素都往前移動(dòng)了一位,所以實(shí)際訪問(wèn)的是第3個(gè)元素。不會(huì)報(bào)出異常,只會(huì)出現(xiàn)漏刪的情況。

foreach循環(huán)刪除元素

for (String s : list) {
        if (s.length() == 4) {
            list.remove(s);
?
        }
    }
    System.out.println(list);

如果沒(méi)有break,會(huì)報(bào)錯(cuò):

java.util.ConcurrentModificationException at java.util.ArrayListItr.checkForComodification(ArrayList.java:911)atjava.util.ArrayListItr.checkForComodification(ArrayList.java:911) at java.util.ArrayListItr.checkForComodification(ArrayList.java:911)atjava.util.ArrayListItr.next(ArrayList.java:861) at com.demo.ApplicationTest.testDel(ApplicationTest.java:64) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)

報(bào)ConcurrentModificationException錯(cuò)誤的原因:

看一下JDK源碼中ArrayList的remove源碼是怎么實(shí)現(xiàn)的:

public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

一般情況下程序會(huì)最終調(diào)用fastRemove方法:

private void fastRemove(int index) {
        modCount++;
        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
    }

在fastRemove方法中,可以看到第2行把modCount變量的值加一,但在ArrayList返回的迭代器會(huì)做迭代器內(nèi)部的修改次數(shù)檢查:

final void checkForComodification() {
     if (modCount != expectedModCount)
             throw new ConcurrentModificationException();
     }

而foreach寫(xiě)法是對(duì)實(shí)際的Iterable、hasNext、next方法的簡(jiǎn)寫(xiě),因?yàn)樯厦娴膔emove(Object)方法修改了modCount的值,所以才會(huì)報(bào)出并發(fā)修改異常。

阿里開(kāi)發(fā)手冊(cè)也明確說(shuō)明禁止使用foreach刪除、增加List元素。

迭代器Iterator刪除元素

    Iterator<String> iterator = list.iterator();
    while(iterator.hasNext()){
        if(iterator.next().length()==4){
            iterator.remove();
        }
    }
    System.out.println(list);

[AA, BBB, EEE]

這種方式可以正常的循環(huán)及刪除。但要注意的是,使用iterator的remove方法,而不是List的remove方法,如果用list的remove方法同樣會(huì)報(bào)上面提到的ConcurrentModificationException錯(cuò)誤。

總結(jié)

無(wú)論什么場(chǎng)景,都不要對(duì)List使用for循環(huán)的同時(shí),刪除List集合元素,要使用迭代器刪除元素。

到此這篇關(guān)于Java中如何正確遍歷刪除List中的元素的文章就介紹到這了,更多相關(guān)Java遍歷刪除List內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實(shí)現(xiàn)調(diào)用對(duì)方http接口得到返回?cái)?shù)據(jù)

    Java實(shí)現(xiàn)調(diào)用對(duì)方http接口得到返回?cái)?shù)據(jù)

    這篇文章主要介紹了Java實(shí)現(xiàn)調(diào)用對(duì)方http接口得到返回?cái)?shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java中關(guān)于 null 的幾種處理方式詳解

    Java中關(guān)于 null 的幾種處理方式詳解

    這篇文章主要介紹了Java中關(guān)于 null 的幾種處理方式,關(guān)于 null ,你應(yīng)該知道下面這幾件事情來(lái)有效的了解 null ,從而避免很多由 null 引起的錯(cuò)誤,具體細(xì)節(jié)跟隨小編一起學(xué)習(xí)下吧
    2021-10-10
  • java實(shí)現(xiàn)郵件發(fā)送

    java實(shí)現(xiàn)郵件發(fā)送

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)郵件發(fā)送,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • IP查詢(xún)系統(tǒng)的異步回調(diào)案例

    IP查詢(xún)系統(tǒng)的異步回調(diào)案例

    本文主要分享了IP查詢(xún)系統(tǒng)的異步回調(diào)案例,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • 淺談Java中各種修飾符與訪問(wèn)修飾符的說(shuō)明

    淺談Java中各種修飾符與訪問(wèn)修飾符的說(shuō)明

    下面小編就為大家?guī)?lái)一篇淺談Java中各種修飾符與訪問(wèn)修飾符的說(shuō)明。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • Java SPI的簡(jiǎn)單小實(shí)例

    Java SPI的簡(jiǎn)單小實(shí)例

    這篇文章主要介紹了Java SPI的簡(jiǎn)單小實(shí)例,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Java高級(jí)特性基礎(chǔ)之反射五連問(wèn)

    Java高級(jí)特性基礎(chǔ)之反射五連問(wèn)

    反射賦予了我們?cè)谶\(yùn)行時(shí)分析類(lèi)以及執(zhí)行類(lèi)中方法的能力。通過(guò)反射你可以獲取任意一個(gè)類(lèi)的所有屬性和方法,你還可以調(diào)用這些方法和屬性。本文就來(lái)和大家詳細(xì)聊聊Java中的反射,感興趣的可以了解一下
    2023-01-01
  • Java基礎(chǔ)之JDK1.8新特性lambda表達(dá)式詳解

    Java基礎(chǔ)之JDK1.8新特性lambda表達(dá)式詳解

    函數(shù)式接口有且僅有一個(gè)抽象方法,但是可以有多個(gè)非抽象方法的接口,函數(shù)式接口可以被隱式轉(zhuǎn)換為lambda表達(dá)式,這篇文章主要介紹了Java基礎(chǔ)之lambda表達(dá)式(JDK1.8新特性),需要的朋友可以參考下
    2023-08-08
  • java 實(shí)現(xiàn)取int型的第二個(gè)字節(jié)的數(shù)

    java 實(shí)現(xiàn)取int型的第二個(gè)字節(jié)的數(shù)

    這篇文章主要介紹了java 實(shí)現(xiàn)取int型的第二個(gè)字節(jié)的數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 淺談mybatis如何半自動(dòng)化解耦(推薦)

    淺談mybatis如何半自動(dòng)化解耦(推薦)

    這篇文章主要介紹了淺談mybatis如何半自動(dòng)化解耦,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06

最新評(píng)論