Java for-each循環(huán)(遍歷循環(huán))詳解
一、本質(zhì)與語法
// 標準語法 (Java 5+)
for (ElementType element : Iterable/Array) {
// 操作element
}
// 等效傳統(tǒng)實現(xiàn)
Iterator<ElementType> it = collection.iterator();
while (it.hasNext()) {
ElementType element = it.next();
// 操作element
}
設(shè)計目標:簡化集合/數(shù)組遍歷,消除顯式迭代器操作
底層機制:
- 對
Iterable對象:自動調(diào)用iterator()獲取迭代器 - 對數(shù)組:轉(zhuǎn)換為傳統(tǒng)索引循環(huán)(編譯后字節(jié)碼可見)
二、核心特性
強制類型安全
List<String> list = Arrays.asList("A", "B");
for (Integer num : list) {} // 編譯錯誤:類型不匹配
不可變性保證
for (final String s : list) {
s = "new"; // 編譯錯誤:final修飾符
}
空指針防護
for (Object obj : null) { ... } // 運行時拋出NullPointerException
三、適用場景與限制
| 支持的數(shù)據(jù)結(jié)構(gòu) | 不支持的操作場景 |
|---|---|
| 所有實現(xiàn)Iterable的集合 | 遍歷時刪除元素(需用Iterator.remove()) |
| 數(shù)組 | 需要反向遍歷 |
| 自定義可迭代對象 | 需要同時訪問索引 |
四、典型錯誤案例
并發(fā)修改異常
List<String> list = new ArrayList<>(Arrays.asList("A", "B"));
for (String s : list) {
list.remove(s); // 拋出ConcurrentModificationException
}
? 修正方案:改用迭代器遍歷 + remove()
對象引用陷阱
List<StringBuilder> list = new ArrayList<>();
list.add(new StringBuilder("Hello"));
for (StringBuilder sb : list) {
sb.append(" World"); // 修改對象內(nèi)部狀態(tài) ??
sb = new StringBuilder(); // 僅改變局部引用 ??
}
五、性能對比分析
| 數(shù)據(jù)結(jié)構(gòu) | for-each | 傳統(tǒng)for循環(huán) | 推薦方案 |
|---|---|---|---|
| ArrayList | 迭代器遍歷(稍慢) | 索引直接訪問(快) | 大數(shù)據(jù)量選傳統(tǒng)式 |
| LinkedList | 迭代器遍歷(快) | 索引遍歷(O(n²)) | 必須用for-each |
| HashSet | 唯一安全遍歷方式 | 無法直接使用索引 | 強制使用for-each |
六、高級應(yīng)用技巧
多維數(shù)組遍歷
int[][] matrix = {{1,2}, {3,4}};
for (int[] row : matrix) {
for (int num : row) {
System.out.print(num + " ");
}
}
自定義可迭代對象
class MyIterable implements Iterable<String> {
public Iterator<String> iterator() {
return Arrays.asList("A","B").iterator();
}
}
并行遍歷優(yōu)化(Java 8+)
list.parallelStream().forEach(element -> {
// 多線程處理(注意線程安全)
});
七、最佳實踐指南
優(yōu)先選擇場景
- 只讀遍歷操作
- 無需索引的線性訪問
- 代碼可讀性要求高
規(guī)避風險策略
// 防御性復(fù)制(針對可能被修改的集合)
for (String s : new ArrayList<>(originalList)) {
originalList.remove(s); // 安全操作
}
類型推斷優(yōu)化(Java 10+)
var entries = Map.of(1,"A",2,"B").entrySet();
for (var entry : entries) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
深度擴展:Java 14引入的Records類型可與for-each循環(huán)完美配合:
record Point(int x, int y) {}
List<Point> points = List.of(new Point(1,2), new Point(3,4));
for (Point(var x, var y) : points) { // 模式匹配解構(gòu)(Java 17預(yù)覽特性)
System.out.println(x + "," + y);
}
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot?Security使用MySQL實現(xiàn)驗證與權(quán)限管理
安全管理是軟件系統(tǒng)必不可少的的功能。根據(jù)經(jīng)典的“墨菲定律”——凡是可能,總會發(fā)生。如果系統(tǒng)存在安全隱患,最終必然會出現(xiàn)問題,這篇文章主要介紹了SpringBoot安全管理Spring?Security基本配置2022-11-11
Java中遍歷Map的多種方法示例及優(yōu)缺點總結(jié)
在java中遍歷Map有不少的方法,下面這篇文章主要給大家介紹了關(guān)于Java中遍歷Map的多種方法,以及各種方法的優(yōu)缺點總結(jié),文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學(xué)習價值,需要的朋友們下面來一起看看吧。2017-07-07
java多線程join()方法的作用和實現(xiàn)原理解析(應(yīng)用場景)
join方法主要是用于將當前線程掛起,等待其他線程結(jié)束后在執(zhí)行當前線程,本文通過應(yīng)用場景分析代碼示例講解java多線程join()方法的作用和實現(xiàn)原理,感興趣的朋友一起看看吧2021-07-07
修改SpringBoot 中MyBatis的mapper.xml文件位置的過程詳解
由于MyBatis默認的mapper.xml的掃描位置是resource文件下,但是不可能整個項目的mapper.xml文件都放在resource下,如果文件較少還行,但是如果文件比較多,太麻煩了,所以本文給大家介紹了修改SpringBoot 中MyBatis的mapper.xml文件位置的過程,需要的朋友可以參考下2024-08-08

