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

Java集合遍歷全指南(迭代器&增強(qiáng)for及列表迭代器)

 更新時(shí)間:2026年02月27日 09:39:50   作者:黎雁  
本文詳盡介紹了Java集合遍歷的5種方式:迭代器、增強(qiáng)for、列表迭代器、普通for及Lambda表達(dá)式,通過代碼示例和原理解析,幫助讀者徹底掌握集合遍歷的核心知識,避免常見錯誤如并發(fā)修改異常和指針復(fù)位問題,適合Java初學(xué)者及面試復(fù)習(xí),需要的朋友可以參考下

文章摘要

  • 閱讀時(shí)長:12 分鐘
  • 適合人群
    1. Java 集合初學(xué)者 → 重點(diǎn)看:迭代器、增強(qiáng) for、Lambda、普通 for、列表迭代器全套用法
    2. 易踩坑:遍歷中增刪元素的同學(xué) → 重點(diǎn)看:并發(fā)修改異常、迭代器 remove、列表迭代器 add
    3. 面試復(fù)習(xí) → 重點(diǎn)看:Iterator 底層原理、cursor 指針、expectedModCount、并發(fā)修改根源
    4. 寫技術(shù)筆記/總結(jié) → 重點(diǎn)看:結(jié)構(gòu)清晰、表格化、細(xì)節(jié)標(biāo)注、完整代碼
  • 本文內(nèi)容
    全覆蓋 迭代器 Iterator、列表迭代器 ListIterator、增強(qiáng) for、遍歷方式匯總、底層源碼,保留所有核心知識點(diǎn),搭配代碼示例+避坑指南+原理拆解,邏輯連貫、干貨拉滿,助力快速掌握集合遍歷精髓。

迭代器與增強(qiáng) for 循環(huán)

一、迭代器遍歷(Iterator 接口)

迭代器是 不依賴索引 的通用遍歷方式,適配所有 Collection 系列集合(List、Set 均可用),是集合專屬的標(biāo)準(zhǔn)遍歷工具,無需關(guān)心集合底層存儲結(jié)構(gòu),只需專注“遍歷取元素”。

獲取迭代器

Collection 集合通過專屬方法獲取迭代器對象,默認(rèn)指針指向集合 0 索引位置:

方法名說明
Iterator<E> iterator()返回迭代器對象,默認(rèn)指向當(dāng)前集合 0 索引

迭代器核心成員方法

迭代器的用法固定,核心就是“判斷有沒有 → 取元素 → (可選)刪元素”三步,常用方法如下:

方法名說明
boolean hasNext()判斷當(dāng)前指針位置是否有元素,有則返回 true,無則返回 false(避免越界)
E next()獲取當(dāng)前指針位置的元素,并將迭代器指針自動移向下一個位置
default void remove()刪除上一次 next() 方法返回的元素(僅迭代器遍歷期間可用)

迭代器四大關(guān)鍵細(xì)節(jié)(必背避坑,少踩90%錯誤)

  1. 邊界異常:當(dāng) hasNext() 返回 false 時(shí),繼續(xù)調(diào)用 next(),會拋出 NoSuchElementException(無此元素異常),切記“先判斷、再取值”。
  2. 指針不復(fù)位:迭代器遍歷完畢后,指針會停留在集合末尾,不會自動回到 0 索引;如果想再次遍歷集合,必須重新調(diào)用 iterator() 方法,獲取一個新的迭代器對象。
  3. next() 調(diào)用規(guī)范:一次循環(huán)中建議只調(diào)用一次 next() 方法,保證 hasNext() 與 next() 一一對應(yīng),避免出現(xiàn)指針錯亂、元素漏取或重復(fù)取的問題。
  4. 并發(fā)修改異常:迭代器遍歷集合期間,不能使用集合自身的 add()、remove() 方法 操作元素(比如 list.add()、list.remove()),否則會拋出 ConcurrentModificationException;若確實(shí)需要刪除元素,只能使用迭代器自身的 remove() 方法;若需要添加元素,普通迭代器無法實(shí)現(xiàn)(需用列表迭代器)。

迭代器遍歷代碼示例(完整可運(yùn)行)

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");

        // 1. 獲取迭代器對象
        Iterator<String> it = list.iterator();

        // 2. 遍歷:先判斷,再取值
        while (it.hasNext()) {
            // 3. 獲取當(dāng)前元素,指針自動后移
            String str = it.next();
            System.out.println(str);

            // 可選:刪除上一次next()返回的元素(此處演示刪除"bbb")
            if ("bbb".equals(str)) {
                it.remove(); // 僅迭代器remove可用,不會拋并發(fā)修改異常
            }
        }

        // 遍歷完畢,指針不復(fù)位,重新遍歷需重新獲取迭代器
        Iterator<String> it2 = list.iterator();
        while (it2.hasNext()) {
            System.out.println(it2.next()); // 輸出:aaa、ccc
        }
    }
}

二、列表迭代器遍歷(ListIterator 接口)

列表迭代器是 List 集合專屬 的遍歷工具,繼承自 Iterator 接口,完全實(shí)現(xiàn)了 Iterator 的所有功能(hasNext()、next()、remove()),同時(shí)新增了“向前遍歷、遍歷中添加元素”的功能,完美解決了普通迭代器不能添加元素的痛點(diǎn)。

列表迭代器常用成員方法(新增+繼承)

方法名說明
boolean hasNext()(繼承)判斷當(dāng)前位置的下一個位置是否有元素,有為 true,無為 false
E next()(繼承)獲取當(dāng)前位置元素,并將迭代器指針移向后一個位置
void remove()(繼承)刪除上一次 next() 或 previous() 方法返回的元素
boolean hasPrevious()(新增)判斷當(dāng)前位置的前一個位置是否有元素,有為 true,無為 false(支持向前遍歷)
E previous()(新增)獲取當(dāng)前位置前一個元素,并將迭代器指針向前移一個位置(向前遍歷核心)
public void add(E e)(新增)將元素插入當(dāng)前指針位置,并將迭代器對象移向后一個位置(遍歷中添加元素)

列表迭代器核心優(yōu)勢

  • 僅 List 集合可用(ArrayList、LinkedList 等),Set 集合不能使用。
  • 支持“雙向遍歷”:既能向后遍歷(next()),也能向前遍歷(previous())。
  • 遍歷期間可自由添加、刪除元素,不會拋出并發(fā)修改異常。

列表迭代器代碼示例(遍歷中添加元素)

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");

        // 1. 獲取List集合專屬的列表迭代器
        ListIterator<String> it2 = list.listIterator();

        // 2. 向后遍歷,遍歷中添加元素
        while (it2.hasNext()) {
            String str2 = it2.next();
            System.out.println(str2);
            // 當(dāng)遍歷到"bbb"時(shí),在其后面添加"qqq"
            if ("bbb".equals(str2)) {
                it2.add("qqq"); // 遍歷中添加,無異常
            }
        }
        System.out.println("添加元素后:" + list); // 輸出:[aaa, bbb, qqq, ccc]

        // 3. 向前遍歷(演示雙向遍歷)
        System.out.println("向前遍歷:");
        while (it2.hasPrevious()) {
            String str3 = it2.previous();
            System.out.println(str3); // 輸出:ccc、qqq、bbb、aaa
        }
    }
}

三、增強(qiáng) for 遍歷

增強(qiáng) for 循環(huán)是 JDK 5 以后引入的語法糖,底層本質(zhì)就是一個 Iterator 迭代器,目的是簡化迭代器的代碼書寫,讓遍歷變得更簡潔、更易讀,無需手動獲取迭代器、判斷 hasNext()、調(diào)用 next()。

增強(qiáng) for 核心特點(diǎn)

  1. 語法極簡,僅用于“遍歷”,不能用于遍歷中添加、刪除元素(否則拋并發(fā)修改異常)。
  2. 適配范圍:所有單列集合(Collection 及其子類)和數(shù)組,雙列集合(Map)不能直接使用。
  3. 遍歷過程中,不能操作集合的索引(無索引相關(guān)方法)。

增強(qiáng) for 標(biāo)準(zhǔn)格式

for(元素的數(shù)據(jù)類型 變量名 : 數(shù)組或者單列集合) {
    // 循環(huán)體:變量名 依次表示集合/數(shù)組中的每一個元素
}

增強(qiáng) for 代碼示例(集合+數(shù)組)

import java.util.ArrayList;
import java.util.List;

public class ForEachDemo {
    public static void main(String[] args) {
        // 1. 增強(qiáng) for 遍歷 List 集合
        List<String> list = new ArrayList<>();
        list.add("zhangsan");
        list.add("lisi");
        list.add("wangwu");

        for (String s : list) {
            System.out.println(s); // s 依次表示集合中的每一個元素
        }

        // 2. 增強(qiáng) for 遍歷數(shù)組
        Integer[] arr = {1, 2, 3, 4, 5};
        for (Integer num : arr) {
            System.out.println(num); // num 依次表示數(shù)組中的每一個元素
        }

        // 重要細(xì)節(jié):修改第三方變量s,不會改變集合本身的值
        for (String s : list) {
            s = "zhaoliu"; // 僅修改變量s的值,集合中的元素不變
        }
        System.out.println("修改后集合:" + list); // 輸出:[zhangsan, lisi, wangwu]
    }
}

實(shí)用小技巧

增強(qiáng) for 快速生成:在 IDEA 中,輸入“集合/數(shù)組名 + for”,按下回車鍵,即可自動生成增強(qiáng) for 循環(huán)代碼,高效又不易出錯。

遍歷方式大匯總(實(shí)用度拉滿)

結(jié)合前面所學(xué),我們整理出 Collection 和 List 集合的所有遍歷方式,明確每種方式的適用場景,避免盲目使用。

一、Collection 集合的三種遍歷方式(通用)

遍歷方式核心適用場景優(yōu)勢不足
迭代器(Iterator)遍歷中需要刪除元素通用、可刪除元素語法相對繁瑣
增強(qiáng) for 循環(huán)僅需要遍歷元素,無需修改語法極簡、易讀不能增刪元素、無索引
Lambda 表達(dá)式遍歷僅需要遍歷元素,追求代碼簡潔最簡潔、代碼量最少不能增刪元素、無索引

簡單總結(jié):

  1. 遍歷中需要刪除元素 → 用 迭代器
  2. 僅僅想遍歷,追求簡潔 → 用 Lambda 或 增強(qiáng) for

二、List 集合的五種遍歷方式(最全)

List 集合因?yàn)橛兴饕?,除了繼承 Collection 的三種遍歷方式,還新增了“普通 for 循環(huán)”和“列表迭代器”兩種方式,共五種,覆蓋所有場景:

遍歷方式核心適用場景優(yōu)勢
迭代器(Iterator)遍歷中需要刪除元素通用、可刪除
列表迭代器(ListIterator)遍歷中需要添加/刪除元素、雙向遍歷可增刪、可雙向遍歷
增強(qiáng) for 循環(huán)僅遍歷,無需修改簡潔易讀
Lambda 表達(dá)式遍歷僅遍歷,追求極簡代碼量最少
普通 for 循環(huán)遍歷中需要操作索引(如修改指定位置元素)可操作索引、靈活

簡單總結(jié):

  1. 遍歷中增刪 → 列表迭代器
  2. 遍歷中刪 → 迭代器
  3. 操作索引 → 普通 for
  4. 僅遍歷 → Lambda / 增強(qiáng) for

全套遍歷方式代碼示例(一次性掌握)

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class AllTraversalDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");

        // 1. 迭代器遍歷(可刪除)
        System.out.println("=== 迭代器遍歷 ===");
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            String str = it.next();
            System.out.println(str);
        }

        // 2. 列表迭代器遍歷(可增刪、雙向)
        System.out.println("=== 列表迭代器遍歷 ===");
        ListIterator<String> it2 = list.listIterator();
        while (it2.hasNext()) {
            String str2 = it2.next();
            if ("bbb".equals(str2)) {
                it2.add("qqq"); // 遍歷中添加
            }
            System.out.println(str2);
        }

        // 3. 增強(qiáng) for 遍歷(僅遍歷)
        System.out.println("=== 增強(qiáng) for 遍歷 ===");
        for (String s : list) {
            System.out.println(s);
        }

        // 4. 普通 for 循環(huán)遍歷(操作索引)
        System.out.println("=== 普通 for 遍歷 ===");
        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            System.out.println(s);
            // 可操作索引:修改指定位置元素
            if (i == 0) {
                list.set(i, "aaa111");
            }
        }

        // 5. Lambda 表達(dá)式遍歷(極簡)
        System.out.println("=== Lambda 遍歷 ===");
        list.forEach(s -> System.out.println(s));
    }
}

Iterator 底層源碼解析(面試高頻)

很多同學(xué)在遍歷集合時(shí)會遇到并發(fā)修改異常,卻不知道根源在哪里;面試中,面試官也常問“迭代器底層原理”,看懂這段源碼,就能徹底搞懂所有問題(以 ArrayList 中的迭代器為例):

// ArrayList 中獲取迭代器的方法
public Iterator<E> iterator() {
    return new Itr(); // 每次調(diào)用iterator(),都會創(chuàng)建一個新的Itr對象(內(nèi)部類)
}

// 迭代器的底層實(shí)現(xiàn):ArrayList的內(nèi)部類Itr,實(shí)現(xiàn)了Iterator接口
private class Itr implements Iterator<E> {
    int cursor;      // 迭代器指針(光標(biāo)),默認(rèn)指向集合0索引
    int lastRet = -1; // 記錄上一次調(diào)用next()返回的元素索引,初始值-1(表示未操作)
    int expectedModCount = modCount; // 記錄集合的修改次數(shù)(創(chuàng)建迭代器時(shí)的初始次數(shù))

    // hasNext()原理:判斷指針是否到達(dá)集合末尾(cursor等于集合大小,說明無元素)
    public boolean hasNext() {
        return cursor != size;
    }

    // next()原理:獲取當(dāng)前指針元素,指針后移,并校驗(yàn)集合是否被修改
    public E next() {
        checkForComodification(); // 核心校驗(yàn):判斷集合是否被非法修改
        int i = cursor; // 記錄當(dāng)前指針位置
        if (i >= size)
            throw new NoSuchElementException(); // 指針越界,拋異常
        Object[] elementData = ArrayList.this.elementData; // 獲取ArrayList底層數(shù)組
        if (i >= elementData.length)
            throw new ConcurrentModificationException(); // 并發(fā)修改異常
        cursor = i + 1; // 指針后移一位
        return (E) elementData[lastRet = i]; // 返回當(dāng)前元素,并更新lastRet
    }

    // 校驗(yàn)集合是否被修改:expectedModCount(迭代器記錄的次數(shù)) != modCount(集合實(shí)際次數(shù))
    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

源碼核心解讀(一句話搞懂)

  1. cursor:迭代器的指針,控制遍歷的位置,默認(rèn)0,每次next()后+1。
  2. modCount:ArrayList 中的成員變量,記錄集合的修改次數(shù)(每調(diào)用一次 add()、remove(),modCount 就自增1)。
  3. expectedModCount:迭代器創(chuàng)建時(shí),復(fù)制一份當(dāng)前集合的 modCount,作為“預(yù)期修改次數(shù)”。
  4. 并發(fā)修改異常根源:遍歷期間,若用集合的 add()、remove() 方法修改元素,會導(dǎo)致 modCount 自增,此時(shí) modCount != expectedModCount,調(diào)用 next() 時(shí),checkForComodification() 校驗(yàn)失敗,拋出異常。

避坑關(guān)鍵

遍歷期間,只要不修改 modCountexpectedModCount 的差值,就不會拋異常:

  • 用迭代器的 remove():會同步更新 expectedModCount,保證與 modCount 一致。
  • 用集合的 add()/remove():僅修改 modCount,不更新 expectedModCount,觸發(fā)異常。

全篇核心干貨總結(jié)(速記版)

  1. 迭代器(Iterator):通用遍歷,可刪不可加,指針不復(fù)位,遍歷中不能用集合方法修改元素。
  2. 列表迭代器(ListIterator):List 專屬,可增可刪、雙向遍歷,解決普通迭代器不能添加的痛點(diǎn)。
  3. 增強(qiáng) for:底層是迭代器,語法極簡,僅用于遍歷,不能增刪元素,修改第三方變量不影響集合。
  4. 遍歷方式選擇:
    • Collection:迭代器(刪)、增強(qiáng) for/Lambda(僅遍歷)
    • List:新增普通 for(操作索引)、列表迭代器(增刪)
  5. 并發(fā)修改異常:根源是 modCount != expectedModCount,遍歷中用迭代器修改元素可避免。
  6. 面試重點(diǎn):Iterator 底層源碼(cursor、modCount、expectedModCount)、列表迭代器新增功能。

寫在最后

集合遍歷是 Java 基礎(chǔ)中最常用、最易出錯的知識點(diǎn),無論是日常業(yè)務(wù)開發(fā)、刷算法題,還是面試,都會高頻遇到。

很多初學(xué)者容易在“遍歷中增刪元素”“指針復(fù)位”“并發(fā)修改異常”這幾個點(diǎn)上踩坑,其實(shí)只要吃透本文的知識點(diǎn),多敲幾遍代碼,理解底層原理,就能輕松規(guī)避所有問題。

建議大家把文中的代碼親手敲一遍,重點(diǎn)練習(xí)“迭代器刪除”“列表迭代器添加”“并發(fā)修改異常規(guī)避”這三個場景,加深記憶。

以上就是Java集合遍歷全指南(迭代器&amp;增強(qiáng)for及列表迭代器)的詳細(xì)內(nèi)容,更多關(guān)于Java集合遍歷指南的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • dubbo服務(wù)注冊到nacos的過程剖析

    dubbo服務(wù)注冊到nacos的過程剖析

    這篇文章主要為大家介紹了dubbo服務(wù)注冊到nacos的過程剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職極限
    2022-02-02
  • Spring?Boot?3.3?實(shí)現(xiàn)職責(zé)鏈模式輕松應(yīng)對電商訂單流程分析

    Spring?Boot?3.3?實(shí)現(xiàn)職責(zé)鏈模式輕松應(yīng)對電商訂單流程分析

    在電商系統(tǒng)中,訂單處理流程包括庫存校驗(yàn)、優(yōu)惠券驗(yàn)證、運(yùn)費(fèi)計(jì)算等多個步驟,這些步驟具有順序依賴性,為了管理這些業(yè)務(wù)邏輯,職責(zé)鏈模式提供了解決方案,通過鏈?zhǔn)疥P(guān)系將處理邏輯模塊化,實(shí)現(xiàn)解耦和靈活擴(kuò)展,本文將探討如何結(jié)合SpringBoot實(shí)現(xiàn)職責(zé)鏈模式,優(yōu)化電商訂單處理流程
    2024-10-10
  • Mybatis傳list參數(shù)調(diào)用oracle存儲過程的解決方法

    Mybatis傳list參數(shù)調(diào)用oracle存儲過程的解決方法

    怎么利用MyBatis傳List類型參數(shù)到數(shù)據(jù)庫存儲過程中實(shí)現(xiàn)批量插入數(shù)據(jù)?接下來通過本文給大家介紹Mybatis傳list參數(shù)調(diào)用oracle存儲過程,需要的朋友可以參考下
    2017-03-03
  • 詳解微信小程序 同步異步解決辦法

    詳解微信小程序 同步異步解決辦法

    這篇文章主要介紹了詳解微信小程序 同步異步解決辦法的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • java中this的用法示例(關(guān)鍵字this)

    java中this的用法示例(關(guān)鍵字this)

    這篇文章主要介紹了java中this的用法示例(關(guān)鍵字this),需要的朋友可以參考下
    2014-03-03
  • Log4j定時(shí)打印日志及添加模塊名配置的Java代碼實(shí)例

    Log4j定時(shí)打印日志及添加模塊名配置的Java代碼實(shí)例

    這篇文章主要介紹了Log4j定時(shí)打印日志及添加模塊名配置的Java代碼實(shí)例,Log4j是Apache的一個開源Java日志項(xiàng)目,需要的朋友可以參考下
    2016-01-01
  • Java for each實(shí)現(xiàn)機(jī)制代碼原理解析

    Java for each實(shí)現(xiàn)機(jī)制代碼原理解析

    這篇文章主要介紹了Java for each實(shí)現(xiàn)機(jī)制代碼原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Java?I/O流之打印流詳細(xì)使用方法教程

    Java?I/O流之打印流詳細(xì)使用方法教程

    java的io是實(shí)現(xiàn)輸入和輸出的基礎(chǔ),可以方便的實(shí)現(xiàn)數(shù)據(jù)的輸入和輸出操作,下面這篇文章主要給大家介紹了關(guān)于Java?IO流打印流詳細(xì)使用的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • SpringBoot集成slf4j2日志配置的實(shí)現(xiàn)示例

    SpringBoot集成slf4j2日志配置的實(shí)現(xiàn)示例

    本文主要介紹了SpringBoot集成slf4j2日志配置的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • Java操作MongoDB事務(wù)未生效的常見場景及解決方案

    Java操作MongoDB事務(wù)未生效的常見場景及解決方案

    在 Java 開發(fā)中,使用 MongoDB 存儲數(shù)據(jù)時(shí),事務(wù)的正確使用至關(guān)重要,然而,在實(shí)際開發(fā)過程中,經(jīng)常會遇到 MongoDB 事務(wù)沒有生效的情況,本文我將結(jié)合多年實(shí)踐經(jīng)驗(yàn),深入剖析事務(wù)未生效的常見場景,并給出詳細(xì)的解決方案,需要的朋友可以參考下
    2025-07-07

最新評論

清河县| 纳雍县| 尼勒克县| 蒲城县| 慈溪市| 沅陵县| 平南县| 咸宁市| 恩平市| 利津县| 北流市| 黄山市| 泊头市| 电白县| 富锦市| 蒙山县| 界首市| 平安县| 上林县| 凤城市| 阜康市| 漳浦县| 德昌县| 尉犁县| 定兴县| 安顺市| 晋州市| 新密市| 靖边县| 孝感市| 大城县| 和龙市| 威信县| 涞源县| 防城港市| 紫阳县| 民勤县| 乐亭县| 鲁山县| 武清区| 宽城|