java基础之foreach

本文解析了Java中foreach循环的工作原理,包括其实现机制及其在不同数据结构上的性能表现。通过对比数组和链表的遍历效率,为开发者提供了实用的性能优化建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

foreach实现原理

集合和数组可以用foreach进行元素访问是因为实现了java.lang.Iterable接口。

jdk api文档中是这样描述Iterable接口的:实现这个接口允许对象成为 "foreach" 语句的目标。不过咋一看Iterable接口并没啥特别之处,只是定义了一个迭代器而已。

public interface Iterable<T> {  

    /** 

     * Returns an iterator over a set of elements of type T. 

     *  

     * @return an Iterator. 

     */  

    Iterator<T> iterator();  
}

我们只需要知道一下事实就好

(1)For-each语法内部,对collection是用nested iteratoration来实现的,对数组是用下标遍历来实现。

(2)Java 5 及以上的编译器隐藏了基于iteration和下标遍历的内部实现。(注意,这里说的是“Java编译器”或Java语言对其实现做了隐藏,而不是某段Java代码对其实现做了隐藏,也就是说,我们在任何一段JDK的Java代码中都找不到这里被隐藏的实现。这里的实现,隐藏在了Java 编译器中,我们可能只能像这篇帖子中说的那样,查看一段For-each的Java代码编译成的字节码,从中揣测它到底是怎么实现的了)

下面对“For-each”和“其对等的iteration/index实现”的对比再简洁明了不过了。

For-each loopEquivalent for loop
for (type var : arr) {
    body-of-loop
}
for (int i = 0; i < arr.length; i++) { 
    type var = arr[i];
    body-of-loop
}
for (type var : coll) {
    body-of-loop
}
for (Iterator<type> iter = coll.iterator(); iter.hasNext(); ) {
    type var = iter.next();
    body-of-loop
}

foreach的限制

(1)使用For-each时对collection或数组中的元素不能做赋值操作。

(2)同时只能遍历一个collection或数组,不能同时遍历多余一个collection或数组。

(3)遍历过程中,collection或数组中同时只有一个元素可见,即只有“当前遍历到的元素”可见,而前一个或后一个元素是不可见的。

(4)只能正向遍历,不能反向遍历(相比之下,C++ STL中还有reverse_iterator, rbegin(), rend()之类的东西,可以反向遍历)。

(5)如果要兼容Java 5之前的Java版本,就不能使用For-each。

foreach和for的性能对比

今天我们来比较一下两种for循环对ArrayList和LinkList集合的循环性能比较。首先简单的了解一下ArrayList和LinkList的区别:
ArrayList:ArrayList是采用数组的形式保存对象的,这种方式将对象放在连续的内存块中,所以插入和删除时比较麻烦,查询比较方便。
LinkList:LinkList是将对象放在独立的空间中,而且每个空间中还保存下一个空间的索引,也就是数据结构中的链表结构,插入和删除比较方便,但是查找很麻烦,要从第一个开始遍历。

public static void main(String[] args) {
       //实例化arrayList  
    List<Integer> arrayList = new ArrayList<Integer>();  
    //实例化linkList  
    List<Integer> linkList = new LinkedList<Integer>();  
    
    //插入10万条数据  
    for (int i = 0; i < 100000; i++) {  
        arrayList.add(i);  
        linkList.add(i);
    }
      
    int array = 0;  
    //用for循环arrayList  
    long arrayForStartTime = System.currentTimeMillis();  
    for (int i = 0; i < arrayList.size(); i++) {  
        array = arrayList.get(i);  
    }  
    long arrayForEndTime = System.currentTimeMillis();  
    System.out.println("用for循环arrayList 10万次花费时间:" + (arrayForEndTime - arrayForStartTime) + "毫秒");  
      
    //用foreach循环arrayList  
    long arrayForeachStartTime = System.currentTimeMillis();  
    for(Integer in : arrayList){  
        array = in;  
    }  
    long arrayForeachEndTime = System.currentTimeMillis();  
    System.out.println("用foreach循环arrayList 10万次花费时间:" + (arrayForeachEndTime - arrayForeachStartTime ) + "毫秒");  
      
    //用for循环linkList  
    long linkForStartTime = System.currentTimeMillis();  
    int link = 0;  
    for (int i = 0; i < linkList.size(); i++) {  
        link = linkList.get(i);  
    }  
    long linkForEndTime = System.currentTimeMillis();  
    System.out.println("用for循环linkList 10万次花费时间:" + (linkForEndTime - linkForStartTime) + "毫秒");  
      
    //用froeach循环linkList  
    long linkForeachStartTime = System.currentTimeMillis();  
    for(Integer in : linkList){  
        link = in;  
    }  
    long linkForeachEndTime = System.currentTimeMillis();  
    System.out.println("用foreach循环linkList 10万次花费时间:" + (linkForeachEndTime - linkForeachStartTime ) + "毫秒");
}
循环10万次的时候,控制台打印结果:

结论:需要循环数组结构的数据时,建议使用普通for循环,因为for循环采用下标访问,对于数组结构的数据来说,采用下标访问比较好。需要循环链表结构的数据时,一定不要使用普通for循环,这种做法很糟糕,数据量大的时候有可能会导致系统崩溃。

<think>好的,用户想学习Javaforeach循环的基础知识,包括用法和示例教程。首先,我需要根据提供的引用内容来整理相关信息,确保回答准确。 首先,引用[1]提到foreach循环是用于遍历数组或集合的简化方式,能提高代码简洁性和可读性。需要先解释基本语法结构,给出数组遍历的示例。然后引用[4]指出foreach适用于实现了Iterable接口的集合类,所以也要展示集合遍历的例子,比如ArrayList。 接下来,用户可能需要知道注意事项,比如不能修改集合元素,否则会抛出异常,这点引用[4]有提到。另外,关于结束循环的问题,引用[2]和[3]讨论了如何终止foreach循环,但根据最佳实践,应该使用传统for循环或Iterator来处理,这部分也需要在注意事项中说明。 最后,生成相关问题时要覆盖常见疑问,比如与for循环的区别、修改元素、性能比较等,确保覆盖用户可能进一步探索的方向。同时,保持回答结构清晰,分点说明,帮助用户逐步理解。</think>### Java foreach循环基础教程 #### 一、基本语法结构 Java foreach循环(增强型for循环)的语法格式为: $$for(元素类型 元素变量 : 集合或数组){// 循环体}$$ #### 二、数组遍历示例 ```java int[] numbers = {3, 9, 5, 7}; for (int num : numbers) { System.out.println("当前元素:" + num); } ``` 该示例会依次输出数组中的每个元素[^1]。 #### 三、集合遍历示例 ```java List<String> fruits = Arrays.asList("Apple", "Banana", "Orange"); for (String fruit : fruits) { System.out.println("水果:" + fruit); } ``` 此语法适用于所有实现`Iterable`接口的集合类(如ArrayList、LinkedList等)[^4]。 #### 四、重要注意事项 1. **不可修改集合**:foreach循环遍历时不能直接增删集合元素,否则会抛出`ConcurrentModificationException` 2. **索引不可见**:无法直接获取当前元素的索引位置 3. **提前终止**:若需要提前终止循环,建议改用传统for循环或迭代器[^2][^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值