作为一个初级程序员来说,对于这三种循环并不是很了解,对于集合或者数组的一个遍历都是想起那个用哪个,并没有实际的去认识到这之间的区别,这篇博文会给大家分享一下最近在工作的遇到的这类问题,以及一些实际的应用。
一:For循环
for循环是传统的循环结构,适用于已知循环次数或需要精确控制循环的情况。在for循环中你需要指定循环的起始条件、循环条件和循环迭代操作。for循环通常用于遍历数组,执行固定次数的操作,或者需要在每次循环中更新迭代变量的情况。
最近在工作中遇到一个问题,就是在利用for循环遍历银行卡,并且根据条件过滤掉一些不再显示的卡,这可能导致一些意外的结果,写一些伪代码供大家参考:
public static void explainFor() {
List<String> bankAccount = new ArrayList<String>();
bankAccount.add("1");
bankAccount.add("2");
bankAccount.add("3");
bankAccount.add("4");
for (int i = 0; i < bankAccount.size(); i++) {
String bankCard = bankAccount.get(i);
if("1".equals(bankCard)) {
bankAccount.remove(i);
}
System.out.println(bankAccount.get(i));
}
}
思考:大家可以先思考一下这种情况下的遍历会出现什么样的问题?
细心的读者会发现,直接在for循环中删除元素会导致列表长度的改变,可能会导致遍历索引和实际元素不匹配,甚至导致一些元素被跳过或重复处理。这就出现不可逆的错误。当然这样的问题也可以设置一个临时变量只保留自己想要的值,就可以避免此类错误。
二: foreach循环
foreach循环用于遍历集合或数组中的元素,更加简洁方便,不需要手动管理索引或迭代变量。它适用于遍历元素数量不固定的情况,例如遍历动态长度的集合或数组。foreach循环不能对集合或数组进行修改,只能用于读取元素。
思考:foreach循环会出现上文中for循环的安全问题吗?
再回答这个问题之前,我们先去了解一下foreach循环的结构和特点:
import java.util.ArrayList;
public class ForEachExample {
public static void main(String[] args) {
// 遍历数组
int[] numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
System.out.print(num + " ");
}
// 输出:1 2 3 4 5
// 遍历List
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
for (String fruit : fruits) {
System.out.print(fruit + " ");
}
// 输出:Apple Banana Orange
}
}
这是一个简单的demo,大家可以很清晰的发现,在此处的索引中并没有显示的出现类似于for循环中的下标,(展开一点原理的介绍:foreach循环底层其实是实现了Iterable接口中的iterator()方法来获取迭代器的,并且实现了接口中的hashNext()和next()方法来遍历集合中的元素的。)所以在foreach循环中是根据内容来遍历的,继而配合remove中的方法,就不会出现上述的安全问题。这也从清晰的回答了上述为什么不会出现for循环的安全问题。
对于foreach循环比起for循环也有不足的地方,如果业务的实现必须根据索引进行操作,比如特定位置元素的删除和修改,foreach循环就不是最合适的选择,这个时候就需要考虑使用传统的for循环,通过索引来访问和修改元素。
三:while循环
while循环是一种基本的循环结构,它根据给定的条件判断来执行循环。在while循环中,循环体会一直重复执行,直到指定的条件为false。 while循环适合处理未知循环次数的情况,因为循环次数取决于条件的满足情况 。
在分析之前大家先回想一下while循环的结构:
import java.util.ArrayList;
import java.util.List;
public class WhileLoopListExample {
public static void main(String[] args) {
// 创建一个List并添加一些元素
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
fruits.add("Grapes");
fruits.add("Mango");
// 使用while循环遍历List并输出元素
System.out.println("水果列表:");
int index = 0;
while (index < fruits.size()) {
String fruit = fruits.get(index);
System.out.println(fruit);
index++;
}
}
}
依据上述代码,while循环的结构还是很清晰的,先判断list中是否有值,之后再去遍历,安全性很高,对于需要先判断list集合是否为空的情况下,可以直接省去这一步骤。
虽然while循环本身不会导致特定的安全问题,但是在while循环时,需要注意以下几个方面:
- 死循环:如果条件判断表达式在循环体内始终为真,将会导致死循环,程序会无限循环下去,不会停止。这可能导致程序卡死,或者占用了过多的计算机资源。确保在循环条件中包含能够终止循环的条件,以避免死循环。
- 并发访问的问题:如果在多线程环境中使用`while`循环,需要注意并发访问的问题。如果多个线程同时对共享数据进行操作,可能导致数据不一致性或竞态条件。在这种情况下,需要考虑使用同步机制(如`synchronized`关键字)来确保线程安全。
- 资源泄露:在`while`循环中使用资源(如文件、网络连接等),需要确保在循环终止时正确地释放这些资源,以避免资源泄露。
总的来说,`while`循环本身没有安全问题,但使用不当可能导致程序错误、资源泄露或死循环等问题。在编写`while`循环时,要小心考虑条件、循环变量的更新,确保循环终止条件正确,并在多线程环境中考虑并发访问的问题,以保证程序的正确性和安全性。
四:总结
在上文的描述中,三种循环各有各的特点和优势,在特定的情况下选择合适的循环方式,是一个成熟的程序员必备的能力,虽然三者得目地都是循环遍历结果,但是对于一些特殊情况就可能会导致一些安全问题的产生。因此对于三种for循环总结如下:
- for循环:
- 用于已知循环次数的情况,通常用于遍历范围内的整数或按步长递增/递减的值。
- 使用计数器或循环变量控制循环的次数。
- 适合处理迭代次数明确的情况。 - while循环:
- 用于未知循环次数的情况,循环条件在循环体内判断。
- 循环在满足条件时重复执行。
- 适合处理不确定循环次数的情况,条件满足时终止循环。 - for-each循环:
- 用于遍历集合或数组中的元素。
- 简化代码,无需手动管理索引,适用于读取元素而不需要修改集合的情况。
- 适合遍历集合的所有元素,简洁方便。
以上就是我对三种循环的浅显理解,一篇博文的分享固然不能涵盖所有的知识,但也希望可以给一些初学者提供游戏额思路和方向,去思考这类基础的用法,从而帮助读者早日成长为可以独当一面的大神,如有疑问和思考欢迎大家评论和探讨。