Java数组
一、方法的多级调用
- 案例:
public class Demo01 { public static void main(String[] args) { System.out.println("准备调用show01"); show01(); System.out.println("main方法结束啦"); } public static void show01() { System.out.println("show01被调用啦"); System.out.println("在show01中调用show02"); show02(); System.out.println("show01调用show02结束"); System.out.println("show01调用结束啦"); } public static void show02() { System.out.println("show02被调用啦"); System.out.println("在show02中调用show03"); show03(); System.out.println("show02调用show03结束"); System.out.println("show02调用结束啦"); } public static void show03() { System.out.println("show03被调用啦"); System.out.println("show03啥也没干...."); System.out.println("show03调用结束啦"); } }
二、递归
- 在方法中调用方法本身
- 可能会造成无穷递归,需要设置合适的出口
- 案例:
public class Demo03 { public static void main(String[] args) { int mul = getMul(5); System.out.println(mul); } /** * 获取阶乘的方法 * @param num * @return */ public static int getMul(int num) { /** * 5! * 5*4*3*2*1 === * 5*4! * 5*4*3! * 5*4*3*2! * 5*4*3*2*1! * */ System.out.println(num); if (num == 1) { return 1; } return num * getMul(num-1); } }
三、方法的重载
- 定义:
- 在同一个类中,出现了名字相同的方法
- 他们的参数列表不同
- 和返回值类型无关
- 案例:
public class Demo04 { public static void main(String[] args) { int sum01 = getSum(3,5); int sum02 = getSum(2,3,5); // getSum(int,int) /** * 在同一个类中 * 出现了名字相同的方法 * 他们的参数列表不同 * 和返回值类型无关 */ } public static int getSum(int i, int j) { return i + j; } public static int getSum(int a, int b,int c) { return a + b + c; } /* * public static void getSum(int a, int b,int c) { System.out.println(a + b + * c);; } */ }
- 参数列表不同的情况
- 参数列表中的形参数量不同
- 参数列表中的形参数据类型不同
- 参数列表中的参数的数据类型顺序不同
- 案例:
public class Demo05 { public static void main(String[] args) { } /** * getSum(int,int) * @param a * @param b * @return */ public static int getSum(int a,int b) { return a+b; } /** * getSum(int,int,int) * @param a * @param b * @return */ public static int getSum(int a,int b,int c) { return a+b+c; } /** * getSum(int,double) * @param a * @param b * @return */ public static double getSum(int a,double b) { return a+b; } /** * getSum(double,int) * @param a * @param b * @return */ public static double getSum(double a,int b) { return a+b; } }
四、数组
- 定义:
- 一组连续的存储空间,存储多个相同数据类型的值
- 创建数组时候必须确定其数据类型和长度
- 数组中的对象在内存中是连续存在的
- 数组中的元素都有一个下标索引,下标从0开始到 数组名.Length-1
- 数组第一个元素的地址及时当前数组的地址
- 数组创建语法【四种】
- 先声明、在分配空间:数据类型 [ ] 数组名; ==》数组名 = new 数据类型[长度];
- 例如:int [ ] array; ==>array = new int[10];
- 声明并分配空间:数据类型 [ ] 数组名 = new 数据类型[长度];
- 例如:int [ ] array = new int [10];
- 声明并赋值(繁):数据类型 [ ] 数组名 = new 数据类型[ ] {value1,value2,calue3........}
- int [ ] array = new int[]{10,20,30,40};
- 声明并赋值(简):数据类型 [ ] 数组名 = {vallue1,value2,value3....}
- int [ ] array = {10,20,30,50,60....}
- 先声明、在分配空间:数据类型 [ ] 数组名; ==》数组名 = new 数据类型[长度];
- 各种类型数组元素的默认值:
- 整型【byte、short、int、long】: 0
- 浮点型【float、double】:0.0
- 布尔型【boolean】:false
- 字符型【char】:\u0000
- 引用类型【类、接口、数组】:null
- 遍历数组:
public class Test01 { public static void main(String[] args) { String[] names = {"宋江","吴用","卢俊义","公孙胜","秦明"}; //遍历数组 for (int i = 0;i<names.length;i++){ System.out.println(names[i]); } } }
- 案例【获取数组中的最大值】
-
public class Demo07 { public static void main(String[] args) { // 获取数字中最大的元素 int[] arr = new int[] {14234,32,34,344,326235,8454321,9,5565432,42}; // 假设第一个元素是最大的 int max = arr[0]; for (int i = 1; i < arr.length; i++) { // 使用max和后面的每一个元素比较 if (arr[i] > max) { // 如果发现比max更大的元素,更改max的值为更大的哪个元素 max = arr[i]; } } System.out.println("数组中最大的元素是:" + max); } }
-
- 获取最大下标
-
public class Demo08 { public static void main(String[] args) { // 找到最大值第一次出现的下标 int[] arr = new int[] {14234,32,34,8454321,8454321,8454321,344,326235,9,5565432,8454321,42}; // 假设最大值的下标是0 int maxIndex = 0; for (int i = 0; i < arr.length; i++) { // maxIndex位置的元素和后面的所有元素比较,如果发现更大的,修改maxIndex的值 if (arr[maxIndex] < arr[i]) { maxIndex = i; } } System.out.println("最大值的下标在" + maxIndex); } }
-
五、数组扩容
- 定义:创建大于原数组的长度的新数组、将原数组元素依次复制到新数组中
- 扩容方式一【循环将原数组中所有元素逐一赋值给新数组】
- 案例:
public static void main(String[] args) { String[] shuiHu = {"西门庆","武松","潘金莲","武大郎"}; String[] xiYou = {"孙悟空","猪八戒","沙僧","白龙马"}; String[] names = new String[shuiHu.length + xiYou.length]; // 放入shuihu中的人物 for (int i = 0; i < shuiHu.length; i++) { names[i] = shuiHu[i]; } // 放入xiyou中的人物 for (int i = shuiHu.length; i < names.length; i++) { names[i] = xiYou[i-shuiHu.length]; } System.out.println(Arrays.toString(names)); }
- 案例:
- 扩容方式二:【使用System.arrayCopy】
- arrayCopy(sec,srcPos,dest,destPos,length)==>src:数据源;srcPos:数据源中的起始位置;dest:目标数组;destPos:目标数据中的起始位置;length:要复制的数组元素数量
- 案例:
public static void main(String[] args) { String[] shuiHu = {"西门庆","武松","潘金莲","武大郎"}; String[] xiYou = {"孙悟空","猪八戒","沙僧","白龙马"}; String[] names = new String[shuiHu.length + xiYou.length]; // 使用System提供的拷贝的方法复制shuihu System.arraycopy(shuiHu, 0, names, 0, shuiHu.length); System.out.println(Arrays.toString(names)); // 使用System提供的拷贝的方法复制xiyou System.arraycopy(xiYou, 0, names, shuiHu.length, xiYou.length); System.out.println(Arrays.toString(names)); }
- 扩容方式三:【使用Arrays.copyOf】
- copyOf(orignal,newLength)==>orignal:要复制的数组;newLength:要返回的副本的长度
- 案例:
public static void main(String[] args) { String[] shuiHu = {"西门庆","武松","潘金莲","武大郎"}; String[] xiYou = {"孙悟空","猪八戒","沙僧","白龙马"}; // 创建新的数组,长度是shuiHu.length+xiYou.length,新的数组会带着ShuiHu中的数据 String[] names = Arrays.copyOf(shuiHu, shuiHu.length+xiYou.length); System.out.println(Arrays.toString(names)); // 复制xiYou的数据到新数组中 System.arraycopy(xiYou, 0, names, shuiHu.length, xiYou.length); System.out.println(Arrays.toString(names)); }
六、引用数组类型的参数
- 定义:在方法中定义的形参,数据类型可以使用基本类型,也可以使用引用类型
- 基本类型和引用类型当做形参
- 案例:
public class Demo05 { public static void main(String[] args) { // 基本类型的数据当做参数传递,传递的是变量的字面值 int num = 110; System.out.println("main:num = " + num); changeNum(num); System.out.println("main:num = " + num); System.out.println("====================="); // 引用类型的数据当做参数传递,传递的是地址值 int[] arr = {111,222,333}; System.out.println("main:arr[0] = " + arr[0]); System.out.println(arr); changeArr(arr); System.out.println("main:arr[0] = " + arr[0]); System.out.println(arr); } public static void changeArr(int[] arr) { arr[0] = 666; System.out.println("changeArr:arr[0] = " + arr[0]); System.out.println(arr); } public static void changeNum(int num) { num = num + 10; System.out.println("changeNum:num = " + num); } }
- 案例:
- 引用数据类型当做返回值
- 案例【合并两个数组。返回合并后的结果】
-
public class Demo06 { public static void main(String[] args) { // 编写一个方法,传入两个数组,得到一个新的、包含原来两个数组的数组 String[] shuiHu = { "西门庆", "武松", "潘金莲", "武大郎" }; String[] xiYou = { "孙悟空", "猪八戒", "沙僧", "白龙马" }; String[] names = mergeArr(shuiHu, xiYou); System.out.println(Arrays.toString(names)); } /** * 合并字符串数组的操作 * @param shuiHu 原数据数组1 * @param xiYou 原数据数组02 * @return 合并之后的数组,包含数组1和数组2中所有的数据 */ public static String[] mergeArr(String[] shuiHu, String[] xiYou) { String[] names = new String[shuiHu.length + xiYou.length]; // 合并的操作 // 先拷贝shuiHu里面的数据 System.arraycopy(shuiHu, 0, names, 0, shuiHu.length); // 再拷贝xiYou里面的数据 System.arraycopy(xiYou, 0, names, shuiHu.length, xiYou.length); return names; } }
七、不定长参数
- 定义:使用于不确定要传入几个参数、如果是相同的参数可以使用不定长参数来接收同类型的数据
- 案例:
public class Demo02 { public static void main(String[] args) { // 编写方法,计算任意个整数的和,获取结果 int sum03 = getSum(3,6,9,12); int sum04 = getSum(3,6,9,12,15); System.out.println(sum04); } /** * 计算4个整数的和 * @param i * @param j * @param k * @param l * @return */ public static int getSum(int i, int j, int k, int l) { return i+j+k+l; } /** * 接收任意个数整数,计算它们的和 * @param nums 传入的所有的整数 * @return 整数的结果 */ public static int getSum(int... nums) { System.out.println(nums); System.out.println(Arrays.toString(nums)); // 记录整数的和 int sum = 0; for (int i = 0; i < nums.length; i++) { sum += nums[i]; } return sum; } }
- 案例:
八、冒泡排序
- 定义:大的的数值排到后面,小的数字排到前面
- 图解:
- 案例:
public static void main(String[] args) { int[] arr = {99,69,96,79,85}; // 确定比较的次数 for (int i = 0; i < arr.length - 1; i++) { // 确定每一轮比较的内容和次数 for (int j = 0; j < arr.length - i - 1; j++) { // 确定比较的规则 if (arr[j] > arr[j+1]) { // 如果j比j+1位置上的数字大,就交换它们的值 int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } System.out.println(Arrays.toString(arr)); }
九、选择排序
- 定义:
- 假定一个最小的元素,记录下标
- 用这个元素和后面的所有元素比较,如果发现更小的,就记录那个更小的元素的小标
- 一轮比较结束后,把原来假设的最小的元素和真正最小的元素交换位置
- 下一轮从下一个位置开始
- 案例:
public static void main(String[] args) { int[] arr = {99,69,96,79,85}; // 确定比较的次数 for (int i = 0; i < arr.length; i++) { // 假设每一轮的第一个是最小的元素的下标 int minIndex = i; // 确定每一轮比较的次数和内容 for (int j = i; j < arr.length; j++) { if (arr[minIndex] > arr[j]) { minIndex = j; } } // 发现了更小的元素,交换一下 int temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } System.out.println(Arrays.toString(arr)); }
十、使用Arrays提供的排序方法
- 定义:
- JDK内置的数组工具类Arrays是专门操作数组的一个工具类
- 提供了复制、转换、排序的方法
- sort方法就是对可以比较的数组进行排序
- 案例:
public class ArraysSort { public static void main(String[] args) { int[] arr = {99,69,96,79,85}; System.out.println("排序前的arr:" + Arrays.toString(arr)); // 升序排序 Arrays.sort(arr); System.out.println("排序后的arr:" + Arrays.toString(arr)); //升序的基础上在降序 for (int i = 0;i<arr.length/2;i++){ int temp = arr[i]; arr[i] = arr[arr.length-1-i]; arr[arr.length-i-1] = temp; } System.out.println(Arrays.toString(arr)); } }
十一、二维数组
- 定义:数组的嵌套,数组中在嵌套数组
- 二维数组的创建语法:
- 先声明、在分配空间:数据类型[ ] [ ] 数组名; 数组名 = new 数据类型 [ 高维长度] [低维长度];
- 例如:int [ ] [ ] arr; arr = new int [5] [5];
- 声明并分配空间: 数据类型[ ] [ ] = new 数据类型 [ 高维长度] [低维长度];
- 例如:int [][] arr= new int [5][10];
- 声明并赋值(繁):数据类型 [] [] 数组名 = new 数据类型[5][]; //不规则数组,自行new低维数组
- 例如:int [][] erwei = new int [5][];
- 声明并赋值(简):数据类型 [] [] 数组名 = {{v1,v2},{v1,v2}}; //显示初始化
- 例如:int [] [] arrv = {{10,20},{10,20}};
- 先声明、在分配空间:数据类型[ ] [ ] 数组名; 数组名 = new 数据类型 [ 高维长度] [低维长度];
- 动态创建二维数组
- 案例:
public static void main(String[] args) { /** * new int[3][5]; * 第一个方括号表示二维数组的长度是3---里面能存放3个一维数组 * 第二个方括号的表示每一个一维数组的长度都是5 */ int[][] arr = new int[3][5]; // 输出二维数组的长度 System.out.println(arr.length); // 输出一维数组的长度 System.out.println(arr[0].length); System.out.println(arr[1].length); System.out.println(arr[2].length); // 动态创建 int[] arr01 = new int[5]; /** * new int[][] * 第一个方括号表示二维数组的长度--这个二维数组中可以存放几个一维数组 * 第二个方括号表示每一个一维数组的长度,创建的时候可以省略,后面需要使用的时候在实例化 */ int[][] arrr01 = new int[3][]; System.out.println(arrr01.length); for (int i = 0; i < arrr01.length; i++) { System.out.println(arrr01[i]); } // 给二维数组中的一维数组赋值 arrr01[0] = new int[2]; arrr01[1] = new int[3]; arrr01[2] = new int[4]; for (int i = 0; i < arrr01.length; i++) { System.out.println(arrr01[i]); } }
- 案例:
- 案例【二维数组遍历】:
public static void main(String[] args) { String[][] names = { {"西游记","奔波儿灞","霸波尔奔","金角大王","银角大王"}, {"三国演义","马超","马岱","马腾","马谡"}, {"水浒传","李逵","李鬼","扈三娘","王英"}, {"红楼梦","贾宝玉","林黛玉","薛宝钗","王熙凤"} }; /** * 遍历 * 先取出每一个一维数组 * 再遍历每一个一维数组 */ // 遍历二维数组,获取每一个一维数组 for (int i = 0; i < names.length; i++) { String[] name = names[i]; // 遍历一维数组,获取每一个元素 for (int j = 0; j < name.length; j++) { System.out.println(name[j]); } } System.out.println(names[1][2]); }
- 图解【二维数组的分配】:
五、字符串相关练习
- 案例【使用startsWith、charAt、equals】
-
public class Demo10 { public static void main(String[] args) { // 输出班级中张姓学员的名字 String[] names = {"张三","李四","王五","张柳","田七","张八","周一"}; // 遍历names,获取每一个人的名字 for (int i = 0; i < names.length; i++) { String name = names[i]; // 获取姓氏 char c = name.charAt(0); // 比较姓氏是不是张 if (c == '张') { System.out.println(name); } } System.out.println("==============="); for (int i = 0; i < names.length; i++) { // 获取每一个人的名字 String name = names[i]; // 使用字符串的startWith方法判定是不是以张开头 if (name.startsWith("张")) { System.out.println(name); } } System.out.println("=============="); // 查找names中有没有张八这个人 for (int i = 0; i < names.length; i++) { // 判断有没有张八这个元素 String name = names[i]; if (name.equals("张八")) { System.out.println(name); } } } }