Java数组
1 - 数组的概念
数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过
编号的方式对这些数据进行统一管理。
2 - 数组的常见概念
①数组名
②下标(或索引)
③元素
④数组的长度:元素的个数
3 - 数组的特点
1.数组是有序排列的
2.数组属于引用类型的变量。数组的元素,既可以是基本数据类型,也可以是引用数据类型
3.创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址
4.数组的长度一旦确定,就不能修改
5.我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快
4 - 数组的分类
1.按照维度:一维数组,二维数组,三维数组
2.按照元素的数据类型分:基本数据类型元素的数组,引用数据类型元素的数组
5 - 一维数组的使用
public class ArrayTest { public static void main(String[] args) { // 1.一维数组的声明和初始化 int num; // 声明 num = 10; // 初始化 int id = 1001; // 声明 + 初始化 int[] ids; // 声明 ids = new int[]{1,2,3};// 1-静态初始化:初始化和数组元素的赋值操作同时进行 String[] names = new String[5]; // 2-动态初始化:初始化和数组元素的赋值操作分开进行 // 错误写法 // int[] array1 = new int[]; // int[5] array2 = new int[]; // int[] array3 = new int[3]{1,2,3}; // 总结:数组一旦初始化完成,其长度就确定了 // 2.如何调用数组的指定位置的元素:通过角标的方式调用。 // 数组的角标(或索引)从0开始的,到数组的长度-1结束。 names[0] = "韩信"; names[1] = "李白"; names[2] = "张飞"; names[3] = "貂蝉"; names[4] = "守约"; // 3.如何获取数组的长度 // 属性:length System.out.println(names.length); // 5 // 4.如何遍历数组 for(int i = 0;i < names.length;i++){ System.out.println(names[i]); } // 5.数组元素的默认初始化值 // >数组元素是整型:0 short[] s1 = new short[2]; // >数组元素是浮点型:0.0 float[] f1 = new float[2]; // >数组元素是char型:0'u0000',而非'0' char[] c1 = new char[2]; // >数组元素是boolean型:false boolean[] b1 = new boolean[5]; // >数组元素是引用数据类型:null String[] arry = new String[5];
6 - 数组的内存解析
1-内存结构
2-数组内存解析
7 - 一维数组练习题
题目1:从键盘读入学生成绩,找出最高分,并输出学生的成绩等级。A级 -(成绩 >= 最高分 - 10),B级-(成绩 >= 最高分 -20),C级-(成绩 >=最高分 - 30),其余的为D级。
import java.util.Scanner; public class Test1 { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.print("请输入学生人数:"); int studentNumber = scan.nextInt(); // 接收数组长度 int[] studentArray = new int[studentNumber]; System.out.println("请输入"+studentNumber+"个学生的考试成绩:"); for(int i = 0;i < studentArray.length;i++){ studentArray[i] = scan.nextInt(); } int max = 0; // if(studentArray[0] > studentArray[1]){ // max = studentArray[0]; // }else{ // max = studentArray[1]; // } for(int i = 0;i < studentArray.length;i++){ if(max < studentArray[i]){ max = studentArray[i]; } } System.out.println("最高分是"+max); String level = ""; for(int i = 0;i < studentArray.length;i++){ if(studentArray[i] >= max-10){ level = "A"; }else if(studentArray[i] >= max-20){ level = "B"; }else if(studentArray[i] >= max-30){ level = "C"; }else{ level = "D"; } System.out.println("Student"+i+"score is"+studentArray[i]+",grade is"+level); } } }
8 - 二维数组的使用
1-Java语言里提供了支持多维数组的语法
2-如果说可以把一维数组当成几何中的线性图形,那么二维数组就相当于是一个表格就像Excel表格一样
3-对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组。
/* * 二维数组的使用 1-理解: 对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。其实, 从数组底层的运行机制来看,其实没有多维数组。 2-二维数组的使用 ①一维数组的声明和初始化 ②如何调用数组的指定位置的元素 ③如何获取数组的长度 ④如何遍历数组 ⑤数组元素的默认值初始化值 ⑥数组的内存解析 */ public class Test2 { public static void main(String[] args){ // 1.二维数组的声明和初始化 int[] array1 = new int[]{1,2,3}; // 一维数组 int[] array1 = {1,2,3}; 类型推断 // 静态初始化 int[][] array2 = new int[][]{{1,2},{10,20,30},{17,50}}; // 动态初始化 String[][] array3 = new String[3][2]; // 相当于 3行 2列 // String array3[][] = new String[3][2]; // 错误写法举例 // String[][] array4 = new String[][2]; // String[][3] array5 = new String[1][2]; // 2.如何调用数组的指定位置的元素 String[][] array4 = new String[][]{{"韩信","李白","刘备"},{"李信","花木兰"},{"后裔"},{"王昭君","貂蝉"}}; // 输出最帅的打野英雄-李白 System.out.println(array4[0][1]); // 李白 // 输出最美的中路英雄-王昭君 System.out.println(array4[3][0]); // 王昭君 // 3.获取数组的长度 System.out.println(array4.length); // 4 System.out.println(array4[0].length); // 3 // 4.遍历二维数组 for(int i = 0;i < array4.length;i++){ for(int j = 0;j < array4[i].length;j++){ System.out.println(array4[i][j]); } } } }
9 - 二维数组元素的默认值初始化值
/* * 规定:二维数组分为外侧数组的元素,内层数组的元素 * int[][] arr = new int[4][3]; * 外侧元素:arr[0],arr[1]等 * 内层元素:arr[0][0],arr[1][2]等 * * 数组元素的默认初始化值 * 针对于初始化方式1:比如:int[][] arr = new int[4][3]; * 外侧元素的初始化值为:地址值 * 内层元素的初始化值为:与一维数组初始化情况相同 * 针对于初始化方式2:比如:int[][] arr = new int[4][]; * 外侧元素的初始化值为:地址值 * 内层元素的初始化值为:不能调用,否则报错 * */ public class ArrayTest3 { public static void main(String[] args) { // 数组元素的默认值初始化值 int[][] array1 = new int[4][3]; // ①数组元素是int System.out.println(array1[0]); // 地址值 System.out.println(array1[0][0]); // 0 float[][] array2 = new float[4][3]; // ②数组元素是float System.out.println(array2[0]); // 地址值 System.out.println(array2[0][0]); // 0.0 String[][] array3 = new String[2][4]; // ③数组元素是String System.out.println(array3[0]); // 地址值 System.out.println(array3[0][0]); // null String[][] array4 = new String[4][]; System.out.println(array4[0]); // null // System.out.println(array4[0][0]); // 报错 } }
10 - 二维数组元素的内存解析与杨辉三角的实现
练习:杨辉三角的实现(打印10行杨辉三角)
@Test public void testYannghui(){ // 打印10行杨辉三角(yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j]) // 1. 声明并初始化二维数组 int[][] yanghui = new int[10][]; // 2. 给数组元素赋值 for(int i = 0;i < yanghui.length;i++){ yanghui[i] = new int[i + 1]; // 2.1给首末元素赋值 yanghui[i][0] = yanghui[i][i] = 1; // 2.2给每行的非首末元素赋值 if(i > 1){ for(int j = 1;j < yanghui[i].length - 1;j++){ yanghui[i][j] = yanghui[i - 1][j - 1] + yanghui[i -1][j]; } } } // 3. 遍历二维数组 for(int i = 0;i < yanghui.length;i++){ for(int j = 0;j < yanghui[i].length;j++){ System.out.print(yanghui[i][j] + " "); } System.out.println(); } }
11 - 数组中涉及的常见算法
1-算法的考查:求数值型数组中元素的最大值,最小值,平均数,总和等。
定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出
所有元素的最大值,最小值,和值,平均值,并输出出来。要求:所有随机数都是两位数。
public class Test3 { public static void main(String[] args){ int[] array1 = new int[10]; for(int i = 0;i < array1.length;i++){ array1[i] = (int)(Math.random() * (99-10+1) + 10); System.out.print(array1[i]+" "); } System.out.println(); // 求数组的最大值 int maxNumber = array1[0]; for(int i = 1;i < array1.length;i++){ if(maxNumber < array1[i]){ maxNumber = array1[i]; } } System.out.println("最大值为"+maxNumber); // 求数组的最小值 int minNumber = array1[0]; for(int i = 1;i < array1.length;i++){ if(minNumber > array1[i]){ minNumber = array1[i]; } } System.out.println("最大值为"+minNumber); // 求数组的所有元素和 int sum = 0; for(int i = 0;i < array1.length;i++){ sum += array1[i]; } System.out.println("总和为"+sum); // 求数组的平均值 double avg = sum/array1.length; System.out.println("平均数为"+avg); } }
2-数组的复制,反转,查找(线性查找,二分法)
/* 使用简单的数组 ①创建一个名为ArrayExer2的类,在main()方法中声明array1和array2两个变量他们是int[]类型的数组。 ②使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19 ③显示array1的内容 ④赋值array2变量等于array1,修改array1中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。打印出array1. 思考:array1和array2是什么关系。 array1和array2地址值相同,都指向了对空间的唯一的数组实体 扩展:修改题目,实现array2 对 array1 的复制 */ public class ArrayExer2{ public static void main(String[] args){ // 1.声明array1和array2两个变量他们是int[]类型的数组。 int[] array1,array2; // 2.把array1初始化为8个素数:2,3,5,7,11,13,17,19 array1 = new int[]{2,3,5,7,11,13,17,19}; // 3.显示array1的内容 for(int i = 0;i < array1.length;i++){ System.out.print(array1[i]+"\t"); } System.out.println(); // 4.赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。打印出array1 array2 = array1; // 不能称作数组的复制 for(int i = 0;i < array2.length;i++){ if(i % 2 == 0){ array2[i] = i; // 修改array2 } System.out.print(array1[i]+"\t"); // 打印array1 } System.out.println(); // 扩展:真正实现数组的复制 实现两个数组完全独立 int[] array3 = new int[]{2,3,5,7,11,13,17,19}; int[] array4 = new int[array3.length]; for(int i = 0;i < array3.length;i++){ array4[i] = array3[i]; System.out.print(array4[i]+"\t"); } System.out.println(); for(int i = 0;i < array3.length;i++){ System.out.print(array3[i]+"\t"); } } }
/* 数组的反转 */ public class Test3{ public static void main(String[] args){ // 数组的反转 String[] array1 = new String[]{"e","d","c","b","a"}; String temp = ""; for(int i = 0;i < array1.length / 2;i++){ temp = array1[i]; array1[i] = array1[array1.length-(i+1)]; array1[array1.length-(i+1)] = temp; } // 数组的遍历 for(int i = 0;i < array1.length;i++){ System.out.print(array1[i]+"\t"); } } }
/* 数组的查找(或搜索) */ public class Test3 { public static void main(String[] args) { // 线性查找 // 找出 李白 String[] strArray = new String[]{"a", "b", "c", "d", "李白"}; String dest = "李白"; boolean tag = false; for (int i = 0; i < strArray.length; i++) { // equals() 方法 判断两个String类型元素的值是否相等 if (dest.equals(strArray[i])) { System.out.println("找到了指定的元素,位置为" + i); tag = true; break; } } if(tag == false){ System.out.println("找不到此元素!"); } } }
/* 数组的查找(或搜索) */ public class Test3 { public static void main(String[] args) { // 二分法查找 // 前提:所要查找的数组必须有序 int[] numberArray = new int[]{1,2,3,10,20,30,55,60,425,785}; int dest = 55; // 假设查找55 int head = 0; // 初始的首索引 int end = numberArray.length - 1; // 初始的末索引 boolean isFlag = true; while(head <= end){ int middle = (head+end)/2; if(dest == numberArray[middle]){ System.out.println("找到了指定的元素,索引位置为"+middle); isFlag = false; break; }else if(dest > numberArray[middle]){ head = middle + 1; }else{ end = middle - 1; } } if(isFlag){ System.out.println("找不到指定的元素!"); } } }
3-数组元素的排序算法
排序算法 1-通常来说,排序的目的是快速查找(如排好序后,用二分法查找,可大大提高查找效率) 2-衡量排序算法的优劣 ①时间复杂度:分析关键字的比较次数和记录的移动次数 ②空间复杂度:分析排序算法中需要多少辅助内存 ③稳定性:若两个记录A和B的关键字值相等,但排序后A,B的先后次序保持不变,则称这种排序算法是稳定的。 3-排序算法的分类:内部排序和外部排序 内部排序:整个排序过程不需要借助外部存储器(如磁盘等),所有排序操作都在内存中完成。 外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘) 。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。 4-10大内部排序算法 ①选择排序 直接选择排序,堆排序 ②交换排序 冒泡排序,快速排序 ③插入排序 直接插入排序,折半插入排序,shell排序 ④归并排序 ⑤桶式排序 ⑥基数排序 */
/* 数组冒泡排序的实现 */ public class Test3 { public static void main(String[] args) { int[] array1 = new int[]{42,54,1,3,58,10,100,21,36}; for(int i = 0;i < array1.length -1;i++){ for(int j = 0;j < array1.length - i - 1;j++){ if(array1[j] > array1[j+1]){ int temp = array1[j]; array1[j] = array1[j+1]; array1[j+1] = temp; } } } for(int i =0;i < array1.length;i++){ System.out.print(array1[i]+"\t"); } } }
/* * 快速排序 1-快速排序通常明显比同为O(nlongn)的其他算法更快,因此常被采用,而且快速排序采用了分治法的思想,所以在很多笔试面试中 能经常看到快排的影子,可见掌握快排的重要性。 2-快速排序(Quick Sort)由图灵奖获得者Tony Hoare 发明,内列为20世纪十大算法之一,迄今为止所有内排序算法中速度最快的一种。冒泡排序 的升级版,交换排序的一种,快速排序的时间复杂度为O(nlog(n). */ public class Test3 { public static void main(String[] args) { // 快速排序的实现 // 代码有点难 } }
12 - 算法的五大特征
13 - 操作数组常用的工具类
import java.util.Arrays; /* java.util.Arrays:操作数组的工具类,里面定义了很多操作数组的方法 */ public class ArraysTest { public static void main(String[] args){ // 1.boolean equals(int[] a,int[] b) 判断两个数组是否相等 int[] array1 = new int[]{1,2,3,4}; int[] array2 = new int[]{4,3,2,1}; boolean isEquals = Arrays.equals(array1,array2); System.out.println(isEquals); // 2.String toString(int[] a) 输出数组的信息 System.out.println(Arrays.toString(array1)); // [1, 2, 3, 4] // 3.void fill(int[] a,int val) 将指定的值填充到数组中 Arrays.fill(array2,10); System.out.println(Arrays.toString(array2)); // [10, 10, 10, 10] // 4.void sort(int[] a) 对数组排序 int[] array3 = new int[]{21,30,11,50,1,2}; Arrays.sort(array3); System.out.println(Arrays.toString(array3)); // 5.int binarySearch(int[] a,int key) 对排好序的数组用二分法进行检索指定的值 int[] array4 = new int[]{1,2,11,21,30,50}; int index = Arrays.binarySearch(array4,30); if(index > 0){ System.out.println(index); }else{ System.out.println("未找到"); } } }
14 - 数组使用中常见的异常
/* 数组使用中常见的异常: 1.数组角标越界的异常 ArrayIndexOutOfBoundsException 2.空指针异常 NullPointerException */ public class ArrayExceptionTest { public static void main(String[] args){ // 1.数组角标越界的异常 ArrayIndexOutOfBoundsException int[] array1 = new int[]{1,2,3}; System.out.println(array1[3]); /* Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 at arrays.test.ArrayExceptionTest.main(ArrayExceptionTest.java:11) */ // 2.空指针异常 NullPointerException // 情况1 int[] array2 = new int[]{1,2,3}; array2 = null; System.out.println(array2[0]); /* Exception in thread "main" java.lang.NullPointerException at arrays.test.ArrayExceptionTest.main(ArrayExceptionTest.java:20) */ // 情况2 int[][] array3 = new int[4][]; System.out.println(array3[0]); // null System.out.println(array3[0][1]); // 报错 // 情况3 String[] array4 = new String[]{"aa","bb","cc"}; array4[0] = null; System.out.println(array4[0].toString()); } }
学习没有捷径,需要日积月累的积淀及对技术的热爱。