- 循环结构-for【重点】
1.1 for循环【重点】
for循环结构,其实就是对while循环的一种特殊简化。在实际开发中使用非常多,必须掌握扎实。
基本语法:
for(1.初始化条件语句; 2.条件判断语句; 4.循环控制语句) { 3. 循环体 } |
执行流程:【重点】
第1次:1. 初始化条件语句 => 2.条件判断语句 => 3. 循环体 => 4. 循环控制语句
第2次:2. 条件判断语句 => 3. 循环体 => 4. 循环控制语句
第3次:2. 条件判断语句 => 3. 循环体 => 4. 循环控制语句
...
最后1次: 2.条件判断语句
代码案例:
public class _05While { public static void main(String[] args) { // 请打印10句,我爱Java,Java让我快乐! // 声明一个int类型变量count表示次数,赋值1 // int count = 1;// 1. 初始化条件 // while (count <= 10) {// count <= 10是 2.循环条件判断 // 打印:我爱Java,Java让我快乐! // System.out.println("我爱Java,Java让我快乐! : " + count);// 3.循环体 【重复干的事】 // count++;// 次数count+1 4.循环控制语句 // } // for循环就是将while循环中部分条件移动到()中 for (int count = 1; count <= 10; count++) { // 打印:我爱Java,Java让我快乐! System.out.println("我爱Java,Java让我快乐! : " + count);// 3.循环体 【重复干的事】 } } } |
注意事项:
- 特殊写法:
- 初始条件中变量的作用域
练习:
1. 输出 1-10的所有的数。 2. 输出 1-10的所有偶数。 3. 求1-10的所有偶数和。 4. 分析题 int i = 0; for(;i++ < 10;i += 2){ System.out.println(++i); } System.out.println("i = " + i); 上面的代码打印的值? 循环了几次? 判断了几次? 最后i的值是多少? 5. 用for循环计算1-10的积。 6. 求出20以内3的倍数的数字和个数。 |
代码实现:
public class _08For { public static void main(String[] args) { // 1.输出 1-10的所有的数 for (int i = 1; i < 11; i++) { System.out.println(i); } // 2.输出 1-10的所有偶数 for (int i = 1; i < 11; i++) { if (i % 2 == 0) { System.out.println(i); } } // 3.求 1-10的所有偶数和 int sum = 0;// 声明一个int类型变量,赋值0,保存和 for (int i = 1; i < 11; i++) { if (i % 2 == 0) { sum += i; } } System.out.println("和:" + sum); // 4. int i = 0; for(;i++ < 10;i += 2){ System.out.println(++i); } System.out.println("i = " + i); // 上面的代码打印的值?2、6、10 // 循环了几次?3 // 判断了几次?4 // 最后i的值是多少?13 // 5.求出20以内3的倍数的数字和个数。 int count = 0;// 声明一个int类型变量count,赋值0,计数个数 for (int j = 1; j <= 20; j++) { // 判断j是否是3的倍数 if (j % 3 == 0) { System.out.println(j); // 计算器+1 count++; } } System.out.println("个数:" + count); } } |
1.2 循环注意事项
/** * 循环注意事项测试:(了解) 1. while(false){}语法错误 2. 死循环后面不能紧跟任何代码 while(true){} for(;;){} 3. while(条件判断);可以不写循环体 4. for循环 4.1 for(){}中初始值可以拿到外部,且可以不写{} 4.2 for(){}死循环是第二个条件判断不写,就是死循环 4.3 for(); 可以不写循环体 */ public class _11ForWhile { public static void main(String[] args) { //1. while(false){}语法错误 // while (false) {} //2. 死循环后面不能紧跟任何代码 // while(true){} // for (;;) {} //3. while(条件判断);可以不写循环体 // while(true); // for (;;); int i = 1; for (; i < 11; ) { System.out.println(i); i++; } } } |
1.3 嵌套循环【目前了解--实际还是掌握】--学习执行顺序即可,千万不要去学习打*
顾名思义,嵌套循环指的是循环中嵌套一个循环【其实就是外层循环的循环体是另外一个循环而已】,但最好嵌套不要超过3层,否则效率太低。
双层循环总结的规律:(当成是轮子,可以直接使用)
外层循环执行一次,内层循环执行所有次
外层循环负责行数,内层负责每一行中列数
循环可以是while、 do while、 for循环任意一种,下面以for循环举例
public class _10ForFor { public static void main(String[] args) { /* * 请打印如下图案:5 * 5 的星星 * ***** * ***** * ***** * ***** * ***** */ // for (int i = 1; i <= 5; i++) { // System.out.println("*****"); // } /* // 每次只能打印一个* // 第1行: ***** for (int i = 1; i <= 5; i++) { // 打印一行中 的每一个 星星 System.out.print("*"); } // 换行 System.out.println(); // 第2行: ***** for (int i = 1; i <= 5; i++) { // 打印一行中 的每一个 星星 System.out.print("*"); } // 换行 System.out.println(); // 第3行: ***** for (int i = 1; i <= 5; i++) { // 打印一行中 的每一个 星星 System.out.print("*"); } // 换行 System.out.println(); // 第4行: ***** for (int i = 1; i <= 5; i++) { // 打印一行中 的每一个 星星 System.out.print("*"); } // 换行 System.out.println(); // 第5行: ***** for (int i = 1; i <= 5; i++) { // 打印一行中 的每一个 星星 System.out.print("*"); } // 换行 System.out.println(); 用循环继续优化代码 */ // 外层循环控制总行数 for (int j = 1; j <= 5; j++) { // 内存for循环控制列数,负责 每一行中 列的输出: ***** for (int i = 1; i <= 7; i++) { // 打印一行中 的每一个 星星 System.out.print("*"); } // 换行 System.out.println(); } /* * 利用好总结出来的规律 * 外层循环执行一次,内层循环执行所有次 外层循环负责行数,内层负责每一行中列数 * 行i 列j ** 1 1 *** 2 2 **** 3 3 ***** 4 4 ****** 5 5 */ for (int i = 1; i < 6; i++) { for (int j = 1; j <= i; j++) { System.out.print("*"); } System.out.println(); } } } |
执行流程分析图:
1.4 循环控制语句【掌握】
1.4.1 概念
对整个循环流程进行控制,可提前终止或跳出循环
1.4.2 控制语句分类【掌握】
1.4.2.1 break
作用:表示结束当前层循环(锚点自己扩展)
1.4.2.2 continue
作用:表示跳过当前次循环,继续下一次循环
|
1.4.2.3 return
作用:表示结束的当前方法
|
代码案例:
public class _09ForControl { public static void main(String[] args) { // 1. 请打印1-200所有6的倍数中前7个 int count = 0;// 声明一个int类型计算器count赋值0 for (int i = 1; i <= 200; i++) { if (i % 6 == 0) { System.out.println(i); // 每次找到一个6的倍数计算器+1 count++; // 判断当前计算器count是否==7,如果是则停止循环 if (count == 7) { break;// 表示结束当前层循环 } } } System.out.println("==============================="); // continue使用跳过当前i=5这一次的打印,继续后面的打印 for (int i = 1; i <= 10; i++) { if (i == 5) { // continue; return; // 表示结束的当前方法 // int a = 1;// 在以上三个控制语句后,不能紧跟任何代码,因为永远执行不到 } System.out.println(i); } System.out.println("循环外部的代码"); // 2. 求1—100之间不能被3整除的数之和大于(或等于)100的第一个数字 continue/break int sum = 0;// 声明一个int类型变量sum,赋值0,保存和 for (int i = 1; i <= 100; i++) { if (i % 3 != 0) { // 打印不是3的倍数的数字i System.out.println(i); // 累加到sum中 sum += i; if (sum >= 100) {// 判断sum>=100的时候结束循环 // 打印当前结束的时候i的值 System.out.println("最后:" + i); break; } } } System.out.println("和:" + sum); int sum2 = 0;// 声明一个int类型变量sum2,赋值0,保存和 for (int i = 1; i <= 100; i++) { // 判断当前i是否是3的倍数,如果是,则跳过这一次循环 if (i % 3 == 0) { continue; } // 打印不是3的倍数的数字i System.out.println(i); // 累加到sum2中 sum2 += i; if (sum2 >= 100) {// 判断sum2>=100的时候结束循环 // 打印当前结束的时候i的值 System.out.println("最后:" + i); break; } } System.out.println("和:" + sum2); } } |
2.数组
2.1数组引入
在之前我们可以通过一个变量表示一个学生的年龄,如果现在需要表示全班 100 个人的年龄岂不是需 要定义 100 个变量来分别表示。这样的操作变量的命名容易冲突,并且也会导致代码量大,可读性差等问题。那么怎么解决这种问题呢?Java 就提供了数组解决这种问题。
2.2数组概念
概念:计算机在内存区域分配的一段连续的区域,用来存储同种类型的数据。
简单的理解,数组就是一堆盒子,同一时间,可以保存多个相同数据类型的数据。
|
1)数组名 :数组的名字
2)数组元素:就是存放在数组里面的数据
3)数组索引:就是数组里面连续存储空间的编号,从0开始
4)length :数组的属性长度,数组名.length拿到数组的长度
数组作用:可以解决同时保存多个数据的问题。
2.3数组声明
回忆定义变量的语法: 数据类型 变量; 如 int age;
数组的声明语法:
数据类型[] 数组名; 【目前只是单纯声明,还不能使用】
如:
int[] ages;// 表示声明一个int类型数组ages,这个数组只能装int类型元素 String[] names;// 表示声明一个String类型数组names,这个数组只能装String类型元素 |
另一种方式:int ages[];【不推荐】
2.4数组赋值
数组在定义后,必须初始化【赋值】才能使用。所谓初始化,就是在堆内存中给数组分配存储空间,并为每一 个元素赋上初始值,有两种方式:
2.4.1 动态创建
语法:数据类型[] 数组名 = new 数据类型[长度];// 长度不能为负数,且是int类型 最大就是int最大值
// 数组声明: 动态创建,语法 :数据类型[] 数组名 = new 数据类型[长度];//长度不能为负数,且是int类型 最大就是int最大值 int[] arr = new int[3];// 动态创建了一个int类型的数组arr,长度3 |
2.4.2 静态创建
语法:数据类型[] 数组名 = {值1, 值2, 值3.....};// 最常用
语法:数据类型[] 数组名 = new 数据类型[]{值1,值2,值3.....};// 不常用。了解
// 数组声明:静态创建,语法 :数据类型[] 数组名 = {元素1, 元素2, 元素3....}; int[] arr2 = {6, 9, 69};// 静态创建了一个int类型的数组arr,赋值元素 :6, 9, 69 |
怎么选择用动态创建还是静态创建?
根据实际情况确定,知道具体的数据,用静态创建,不知道用动态创建。
2.4.3 数组赋值
语法:数组名[下标] = 值;
// 2 数组赋值:语法,数组名[下标] = 值; arr[0] = 1;// 给数组arr第1个元素赋值1 arr[1] = 2;// 给数组arr第2个元素赋值2 arr[2] = 3;// 给数组arr第3个元素赋值3 |
2.5 数组取值
语法:数组名[下标];
取值后,主要用于:
- 直接打印输出
- 赋值给另外一个变量
- 直接计算
- 作为方法参数使用【后面讲】
// 数组取值:语法,数组名[下标]; 直接打印元素即可 System.out.println("第1个元素 : " + arr[0]);// 直接打印第1个元素 System.out.println("第2个元素 : " + arr[1]);// 直接打印第2个元素 System.out.println("第3个元素 : " + arr[2]);// 直接打印第3个元素 |
2.6 数组遍历
遍历:就是将数组中每一个元素取出来。
2.5.1 for + index【普通for循环】
根据上面取值的代码,可以发现一个规律,下标都是从0开始,到length-1结束。因此我们通过循环可以得到下标,而得到下标后,进而可以通过下标获取对应元素:
数组遍历【将所有元素取出来就是遍历】 // 先打印数组arr所有下标 for (int i = 0; i < arr.length; i++) {// i表示下标,循环次数就是到 最后一个下标arr.length - 1 // 打印下标:i System.out.println("下标:" + i); // 打印元素:arr[i]【通过下标获取对应元素】 System.out.println("元素==== :" + arr[i]); } |
2.5.2 增强for循环
1.1概念:
增强for循环就是类似for循环的结构,专业称呼为foreach
2. 作用: 只是用来简化遍历数组和集合的过程;
3. 缺点: 没有索引,凡是涉及有索引相关操作还是用普通for循环;
语法:
for(元素类型 e : 数组/集合){
e就是每次获取到的元素
}
/* * 数组遍历第二种方式:增强for循环 foreach * * 方式2: 简化遍历数组的过程 * 2. 增强for循环: foreach 语法: for(元素数据类型 变量名 : 数组名){ 变量名//就是每一次获取到的元素 } */ for (int e : arr) {// arr是数组名, int 是元素类型 e变量是每一个元素 System.out.println("元素 :" + e); } |
怎么选择用普通for循环还是增强for循环?
如果要操作某一个具体的元素的时候,用普通for循环,因为操作元素需要通过下标
。如果只是遍历的话,用增强for循环 foreach
2.7 数组的内存图
/** * 数组内存分析图【理解】 * 基本类型具体的值在栈帧中 * 引用类型具体的值在堆中 */ public class _05StackHeap { public static void main(String[] args) { int[] arr2 = {1, 2, 5}; int[] arr = new int[3]; System.out.println(arr[0]); System.out.println(arr[1]); System.out.println(arr[2]); System.out.println(arr); arr[0] = 1; arr[1] = 9; arr[2] = 6; // arr[3] = 5;// ArrayIndexOutOfBoundsException 数组下标越界异常。证明下标超过了数组有效范围 int a = 1; int b = 1; a = 2; } } 分析图: |
2.8 数组注意事项
1 数组的下标范围是[0,arr.length-1],使用数组的时候,超过下标范围会报错
ArrayIndexOutOfBoundsException 数组下标越界异常。
例如:数组长度是3个,但是现在操作第4个元素arr[3]就会报这个错误。
2 数组动态创建可以分为两步:
2.1. int[] arr;//只是声明一个int类型的数组,还没有创建(即,还没有分配内存空间)
2.2. arr = new int[长度];//分配内存空间,动态创建数组
3 数组静态创建可以分为两步:
3.1. int[] arr;//只是声明一个int类型的数组,还没有创建(即,还没有分配内存空间)
3.2. arr = new int[]{1,2,43};// 分配内存空间,动态创建数组
不能直接这样写:arr = {1,2,43};// 语法错误
4 数组一旦创建,长度就固定不变了。
如果长度不够或者长度多了,就需要创建新数组,将原来数组中元素复制到新数组中。int[] arr = {1,2,43};
arr = new int[]{1,43};//开辟新的内存区域,重新创建新的数组扩容、缩容
5 数组是引用数据类型,直接打印数组名是打印的地址
6 动态创建,没有给数组元素赋值,则系统会分配默认值
(byte/short/int/long)整数类型默认值:0
(float、double)小数类型默认值:0.0
boolean类型:false
char类型默认值:空字符
7 空指针异常:NullPointerException,操作了一个尚未初始化或者没有分配内存空间的数组,即只声明了变量,没有创建数组。
8 数组声明可以这样,但是不建议
int arr[] = new int[2];// []在数组名后,不建议
部分测试代码
public class _06Array { /** static修饰int[]类型成员变量newArr,声明不赋值 */ static int[] newArr; public static void main(String[] args) { // 静态创建分2步 int[] arr2; // 创建 arr2 = new int[]{1, 2, 5}; // 动态创建分2步 int[] arr; arr = new int[2]; // 使用成员变量newArr System.out.println(newArr);// null // 使用成员变量newArr.length System.out.println(newArr.length);// NullPointerException空指针异常 int arr3[] = new int[2];// 不建议 } } |
2.9 数组练习题
public static void main(String[] args) { // 需求 1:找出数组nums中元素 22 第一次出现的索引位置 int[] nums = {11, 22, 33, 44, 22, 55}; /* * 分析:普通for循环【因为用下标】,遍历数组nums,将每一个元素跟22比较,如果相等,就打印下标,结束break循环 */ // 普通for循环【因为用下标】,遍历数组nums for (int i = 0; i < nums.length; i++) { // if判断,将每一个元素nums[i]跟22比较,如果相等 if (nums[i] == 22) { // 如果相等,就打印下标 System.out.println("下标:" + i); // 结束break循环 break; } } // 需求 2:求出数组nums2中所有元素的和 int[] nums2 = {11, 22, 33, 44, 22, 55}; // 遍历全部不用下标,用foreach循环 // 声明一个int变量sum装和,赋值0 int sum = 0; for (int e : nums2) { // 将每一个元素e累加到sum中 sum += e; } System.out.println("和:" + sum); // 需求 3:求出数组nums3中所有偶数元素、奇数元素的和 int[] nums3 = {11, 22, 33, 44, 22, 55}; int evenSum = 0;// 声明一个int变量evenSum装偶数和,赋值0 int oddSum = 0;// 声明一个int变量oddSum装奇数和,赋值0 // 遍历全部不用下标,用foreach循环 for (int e : nums3) { // 判断当前元素e是否是偶数,如果是累加到evenSum中,如果不是则累加到oddSum if (e % 2 == 0) {// 判断e是否是偶数 evenSum += e; } else { oddSum += e; } } System.out.println("偶数和:" + evenSum + " 奇数和:" + oddSum); } int[] nums = {11, 22, 33, 44, 22, 55}; System.out.println(nums);// 打印的是地址,没有意义 /* * 需求 4:希望将该数组进行字符串拼接,这样我们就你可以打印字符串的指定格式: [元素1, 元素2, 元素3....] * 思路:要遍历数组,将数组元素进行字符串拼接 * 步骤: * 1. 声明一个String类型str,赋值为"[",用来拼接字符串的 * 2. 遍历数组nums,初始化条件,从下标0开始,循环结束条件到倒数第二个元素 * 每次循环,都将获取到的元素nums[i]拼接到str中,然后在继续拼接一个逗号 * 3. 循环结束后,再将最后一个元素nums[nums.length - 1]拼接上,拼接 结尾] */ // 1. 声明一个String类型str,赋值为"[",用来拼接字符串的 String str = "["; // 2. 遍历数组nums,初始化条件,从下标0开始,循环结束条件到倒数第二个元素 for (int i = 0; i <= nums.length - 2; i++) { // 每次循环,都将获取到的元素nums[i]拼接到str中 str += nums[i] + ", "; } System.out.println(str); // 3. 循环结束后,再将最后一个元素nums[nums.length - 1]拼接上,拼接 结尾] str += nums[nums.length - 1] + "]"; System.out.println("拼接后: " + str); // 需求5:求出数组arr中的最大值 int[] arr = {11, 22, 33, 44, 22, 55}; /* * 思路: * 将第一个和第二个比较大小,找出最大的,保存到临时变量中,然后继续跟下一个比较,一直比较到最后一个元素,循环结束后,最大的值就找到了 */ int max = arr[0];// 声明一个临时变量max,赋值arr第一个元素,保存的都是遍历到的最大值 // 普通for循环,下标从1开始 for (int i = 1; i < arr.length; i++) {// 下标从1开始,到最后一个元素结束 // 将当前遍历到的元素arr[i]跟临时变量max比较,如果当前元素arr[i]>max,就给max重新赋值 if (arr[i] > max) { max = arr[i];//就给max重新赋值为当前元素arr[i] } } System.out.println("最大值:" + max); // 需求6:求出数组arr中的最大和最小值 int max2 = arr[0];// 声明一个临时变量max2,赋值arr第一个元素,保存的都是遍历到的最大值 int min = arr[0];// 声明一个临时变量min,赋值arr第一个元素,保存的都是遍历到的最小值 // 普通for循环,下标从1开始 for (int i = 1; i < arr.length; i++) {// 下标从1开始,到最后一个元素结束 // 将当前遍历到的元素arr[i]跟临时变量max2比较,如果当前元素arr[i]>max2,就给max2重新赋值 if (arr[i] > max2) { max2 = arr[i];//就给max2重新赋值为当前元素arr[i] } // 将当前遍历到的元素arr[i]跟临时变量min比较,如果当前元素arr[i]<min,就给min重新赋值 if (arr[i] < min) { min = arr[i];//就给min重新赋值为当前元素arr[i] } } System.out.println("======最大值:" + max2); System.out.println("======最小值:" + min); // 需求7:请将"我" "爱" "你" 存入数组,然后正着和反着输出 String[] iLoveYou = {"我", "爱", "你"}; // 正序输出 for (String s : iLoveYou) { System.out.println(s); } // 反着输出 for (int i = iLoveYou.length - 1; i >= 0; i--) { System.out.println(iLoveYou[i]); } |