数组的概述
一维数组
声明
初始化
数组元素的引用
数组元素的默认初始化值
public class OneArrayTest {
public static void main(String[] args) {
//1.数组的声明与初始化
//复习:变量的定义格式:数据类型 变量名=变量值
int num1 = 10;
int num2; //声明
num2 = 20; //初始化
//1.1 声明数组
double[] prices;
//1.2 数组的初始化
//静态初始化:数组变量的赋值与数组元素的赋值操作同时进行。
prices = new double[]{20.32,43.21,43.22};
// String[] foods;
// foods = new String[]{"拌海蜇", "龙须菜", "炝冬笋", "酱茄子"};
// String[] foods;
// foods = new String[4];
//数组的声明和初始化
// 动态初始化:数组变量的赋值与数组元素的赋值操作分开进行。
String[] foods = new String[4];
//其他正确的方式
int arr[] = new int[4];
int[] arr1 = {1,2,3,4}; //类型推断
int arr4[] = {1,2,3};
//错误的方式
//int[] arr2 = new int[3]{1,2,3}; // 动静结合
//int[3] arr3 = new int[];
//2.数组元素的调用
// 通过角标的方式,获取数组的元素
// 角标的范围从0开始,到数组的长度-1结束
System.out.println(prices[0]);
System.out.println(prices[2]);
//System.out.println(prices[4]); //报异常:ArrayIndexOutOfBoundsException
foods[0] = "拌海蜇";
foods[1] = "龙须菜";
foods[2] = "炝冬笋";
foods[3] = "酱茄子";
//foods[4] = "酱茄子"; //报异常:ArrayIndexOutOfBoundsException
//3.数组的长度:用来描述数组容器中容量的大小
//使用length属性表示
System.out.println(foods.length); // 4
System.out.println(prices.length); //3
//4.如何遍历数组
// System.out.println(foods[0]);
// System.out.println(foods[1]);
// System.out.println(foods[2]);
// System.out.println(foods[3]);
for (int i = 0; i < foods.length; i++) {
System.out.println(foods[i]);
}
for (int i = 0; i < prices.length; i++) {
System.out.println(prices[i]);
}
}
}
一维数组的使用
一维数组的内存解析
package com.atguigu1.one;
/**
* ClassName: OneArrayTest1
* Package: com.atguigu1.one
* Description:
*
* @Author: shkstart
* @Create 2025-03-17 15:38
* @Version: 1.0
*/
public class OneArrayTest1 {
public static void main(String[] args) {
//5.数组元素的默认初始化值
int[] arr1 = new int[3]; //动态初始化
System.out.println(arr1[0]);//0
short[] arr2 = new short[4];
for (int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
}
//浮点型数组元素的默认值初始化值:0.0
double[] arr3 = new double[5];
System.out.println(arr3[0]);
// 字符型数组元素的默认初始化值:0(或理解为'\u0000')
char arr4[] = new char[4];
System.out.println(arr4[0]);
if(arr4[0] == 0){
System.out.println("1111"); //1111
}
if(arr4[0] == '0'){
System.out.println("2222"); //不输出,字符型初始化值不为'0'
}
if(arr4[0] == '\u0000'){
System.out.println("3333");//3333
}
//>boolean型数组元素的默认初始化值:false
boolean[] arr5 = new boolean[5];
System.out.println(arr5[0]);
//>引用数据类型数组元素的默认初始化值: null
String[] arr6 = new String[5];
for(int i = 0 ; i < arr6.length ; i++){
System.out.println(arr6[i]);
}
if(arr6[0] == null){
System.out.println("aaa"); //aaa
}
if(arr6[0] == "null"){
System.out.println("bbb"); //不输出
}
//6.数组的内存解析
}
}
练习题:
多维数组
多维数组的使用
package com.atguigu2.two;
/**
* ClassName: TwoArrayTest
* Package: com.atguigu2.two
* Description:
*
* @Author: shkstart
* @Create 2025-03-17 17:56
* @Version: 1.0
*/
public class TwoArrayTest {
public static void main(String[] args) {
//1.数组的声明与初始化
//复习
int[] arr1 = new int[]{1,2,3};
//1.方式1:静态初始化:数组变量的赋值和数组元素的赋值分开进行
int[][] arr2 = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
//方式2:动态初始化1:数组变量的赋值和数组元素的赋值分开进行
String[][] arr3 = new String[3][4];
//方式2:动态初始化2
double[][] arr4 = new double[2][];
//其他正确写法
int arr5[][] = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
int[] arr6[] = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
int arr7[][] = {{1,2,3},{4,5},{6,7,8,9}};
String arr8[][] = new String[3][4];
//错误的写法:
//int[][] arr9 = new int[3][4]{{1,2,3},{4,5,6},{7,8,9}};
//int[3][4] arr10 = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
//int[][] arr11 = new int[][10];
//2.数组元素的调用
//针对于arr2来说,外层元素{1,2,3},{4,5},{6,7,8,9}内层元素:1,2,3,4,5,6,7,8,9
//调用内层元素
System.out.println(arr2[0][0]); //1
System.out.println(arr2[2][1]); //7
System.out.println(arr2[2]); //打印出来是个地址值[I@4eec7777,指向的是一位数组的地址
//测试arr3,arr4
arr3[0][1] = "Tom";
System.out.println(arr3[0][1]); //Tom
System.out.println(arr3[0]); //[Ljava.lang.String;@3b07d329 前面表示的是数组的类型,后面就是一维数组的地址
arr4[0] = new double[4];
arr4[0][1] = 1.0;
System.out.println(arr4[0][1]); //1.0
//3.数组的长度
System.out.println(arr2.length); //3
System.out.println(arr2[0].length); //3
System.out.println(arr2[1].length); //2
System.out.println(arr2[2].length); //4
//4.如何遍历数组
for (int i = 0; i < arr2.length; i++) {
for (int j = 0; j < arr2[i].length; j++) {
System.out.print(arr2[i][j] + " ");
}
}
}
}
二维数组的内存解析
public class TwoArrayTest1 {
public static void main(String[] args) {
//5.数组元素的默认初始化值
//以动态初始化方式1说明:
int[][] arr1 = new int[3][2];
//外层元素默认值:
System.out.println(arr1[0]); //地址值 [I@4eec7777
System.out.println(arr1[1]); //地址值 [I@3b07d329
//内层元素默认值
System.out.println(arr1[0][0]); //0
boolean[][] arr2 = new boolean[3][4];
//外层元素默认值:
System.out.println(arr2[0]);//地址值
//内层元素默认值
System.out.println(arr2[0][0]); //false
String[][] arr3 = new String[4][2];
//外层元素默认值:
System.out.println(arr3[0]);//地址值 [Ljava.lang.String;@404b9385
//内层元素默认值
System.out.println(arr3[0][0]); //null
//****************************
//以动态初始化方式2说明:
int[][] arr4 = new int[4][];
//外层元素默认值:
System.out.println(arr4[0]);//null
//内层元素默认值:
System.out.println(arr4[0][0]);//报错 NullPointerException
// String[][] arr5 = new String[5][];
// //外层元素默认值:
// System.out.println(arr5[0]);//null
// //内层元素默认值:
// System.out.println(arr5[0][0]);//报错 NullPointerException
//6.数组的内存解析
}
}
数组中涉及到的常见算法
题目练习:
案例:声明:int[] x,y[];在给x,y变量赋值以后,以下选项允许通过编译的是: 声明:int[] x,y[];在给x,y变量赋值以后,以下选项允许通过编译的是: 6;d) a) x[0]= y; no b) y[0]= x yes c) y[0][0] = x; no d) x[0][0]= y; no e) y[0][0]= x[0]; yes f) x = y; no 提示: 一维数组:int[] x 或者int x[] 二维数组:int[][] y或者 int[] y[] 或者 int y[][]public class ArrayExer02 { public static void main(String[] args) { // = : 赋值符号 int i = 10; int j = i; long l = i; // 自动类型提升 byte b = (byte) i; // 强制类型转换 //举例:数组 int[] arr1 = new int[10]; byte[] arr2 = new byte[20]; //arr1 = arr2; //编译不通过,原因:int[],byte[] 是两种不同类型的引用变量 System.out.println(arr1); System.out.println(arr2); int[][] arr3 = new int[3][2]; // arr3 = arr1; //编译不通过 arr3[0] = arr1; //数组类型和维数一致才可以赋值 System.out.println(arr3[0]); //[I@4eec7777 System.out.println(arr1); //[I@4eec7777 } }
杨辉三角
案例:使用二维数组打印一个 10 行杨辉三角。 提示: 1.第一行有 1 个元素,第 n 行有 n 个元素 2.每一行的第一个元素和最后一个元素都是 1 3.从第三行开始,对于非第一个元素和最后一个元素的元素。即: yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];public class YangHuiTest { public static void main(String[] args) { //1.创建二维数组 int[][] yanghui = new int[10][]; //2.使用循环结构,初始化外层数组元素 for (int i = 0; i < yanghui.length; i++) { yanghui[i] = new int[i+1]; //3.给数组的元素赋值 //3.1给数组每行的首末元素赋值为1 yanghui[i][0] = yanghui[i][i] = 1; //3.2给数组每行的非首末元素赋值 //if(i>=2){ //这个判断可以去掉 for(int j=1;j<yanghui[i].length-1;j++){ //j从每行的第2个元素开始,到倒数第2个元素结束 yanghui[i][j] = yanghui[i-1][j] + yanghui[i-1][j-1]; } //} } for (int i = 0; i < yanghui.length; i++) { for (int j = 0; j < yanghui[i].length; j++) { System.out.print(yanghui[i][j] + "\t"); } System.out.println(); } } }
数组的复制
public class ArrayExer04_1 {
public static void main(String[] args) {
// (1)创建一个名为ArrayTest的类,在main()方法中声明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");
}
// (4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
//array2 = array1; //array2与array1指向了同一个地址值,修改其中的任何一个,这两个变量的值都会改变
array2 = new int[array1.length];
for (int i = 0; i < array1.length; i++) {
array2[i] = array1[i];
}
for (int i = 0; i < array2.length; i++) {
if(i%2==0){
array2[i] = 2*i;
}
}
System.out.println(array2);
// (5)打印出array1.
for (int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + "\t");
}
}
}
数组的反转
案例: 定义数组:int[] arr =new int[]{34,54,3,2,65,7,34,5,76,34,67}; 如何实现数组元素的反转存储?你有几种方法。public class ArrayExer05 { public static void main(String[] args) { int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67}; for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } System.out.println(); //反转操作 //方式1: //for (int i = 0; i < arr.length; i++) { //前一半与后一半反转,只需要执行数组的一般即可,前一半反转之后,后一半继续反转,返回的结果值就是原来的值 // for (int i = 0; i < arr.length/2; i++) { // //交互arr[arr.length - 1 - i]与arr[i]位置的元素 // int temp = arr[i]; // arr[i] = arr[arr.length - 1 - i]; // arr[arr.length - 1 - i] = temp; // } //方式2: for(int i = 0, j = arr.length-1; i<j;i++,j--){ //交换arr[i]与arr[j]位置的元素 int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } //方式3:不推荐 // int[] newArr = new int[arr.length]; // for(int i = arr.length - 1; i>=0; i--) { // newArr[arr.length - 1 -i] = arr[i]; // } // for(int i = 0;i<newArr.length;i++) { // System.out.print(newArr[i] + "\t"); // } // System.out.println(); //遍历 for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } } }
数组的扩容
案例1:数组的扩容: 现有数组 int[] arr=new int[]{1,2,3,4,5}; 现将数组长度扩容1倍,并将10,20,30三个数据添加到arr数组中,如何操作?public class ArrayExer01_1 { public static void main(String[] args) { int[] arr = new int[]{1,2,3,4,5}; //扩容1倍的空间 // int[] newArr = new int[arr.length *2]; //或 int[] newArr = new int[arr.length << 1]; //将原来的数组中的元素复制到新的数组中 for (int i = 0; i < arr.length; i++) { newArr[i] = arr[i]; } //将10,20,30三个数据添加到新的数组中 newArr[arr.length] = 10; newArr[arr.length + 1] = 20; newArr[arr.length + 2] = 30; //将新的数组的地址赋值给原有的数组变量 arr = newArr; //遍历arr for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]+"\t"); //1 2 3 4 5 10 20 30 0 0 } } }
数组的缩容
案例:数组的缩容: 现有数组 int[] arr={1,2,3,4,5,6,7}。现需删除数组中索引为4的元素public class ArrayExer01_2 { public static void main(String[] args) { int[] arr = { 1, 2, 3, 4, 5, 6, 7}; int deleteIndex = 4; //方式1:不新建数组 // for (int i = deleteIndex; i < arr.length-1; i++) { // arr[i] = arr[i+1]; // } //修改后元素,设置为默认值 //arr[arr.length - 1] = 0; //方式2:新建数组,新的数组的长度比原来数组的长度少1个 int[] newArr = new int[arr.length-1]; for(int i = 0; i < deleteIndex; i++){ newArr[i] = arr[i]; } //新数组比原有的数组长度少1 i < arr.length-1 for(int i = deleteIndex; i < arr.length-1;i++){ newArr[i] = arr[i+1]; } arr = newArr; //遍历arr数组 for(int i = 0; i<arr.length; i++){ System.out.print(arr[i]+"\t"); //1 2 3 4 6 7 } } }
线性查找,二分法查找
案例1:线性查找 定义数组:int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67}; 查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。public class LinearSearchTest { public static void main(String[] args) { int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67}; int target = 5; //target = 15; //查找方式:线性查找 //方式1: boolean isFlag = true; // for (int i = 0; i < arr1.length; i++) { // if(arr1[i] == target){ // System.out.println("找到了"+target+",对应的位置为"+i); //找到了5,对应的位置为7 // isFlag = false; // break; // } // } //通过isFlag可以来判断没有找到的提示 // if(isFlag){ // System.out.println("不好意思,没有找到此元素"); // } //方式2 int i = 0; for (; i < arr1.length; i++) { if(arr1[i] == target){ System.out.println("找到了"+target+",对应的位置为"+i); //找到了5,对应的位置为7 isFlag = false; break; } } //通过判断i是否等于数组长度,可以来判断,是通过找到了数组当中的元素,通过break退出的循环,还是没有找到元素,通过for循环遍历完了来退出的循环 if(i == arr1.length){ System.out.println("不好意思,没有找到此元素"); } } }
案例2:二分法查找,数组必须有序 定义数组:int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100}; 查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。public class BinarySearchTest { public static void main(String[] args) { int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100}; int target = 17; int head = 0; //默认的首索引 int end = arr2.length - 1; //默认的尾索引 boolean isFlag = false; //判断是否找到了指定元素 while(head <=end){ int middle = (head + end)/2; if(target == arr2[middle]){ System.out.println("找到了" + target + ",对应位置为" + middle); isFlag = true; break; }else if(target > arr2[middle]){ head = middle + 1; }else{ end = middle - 1; } } if(!isFlag){ System.out.println("不好意思,未找到元素"); } } }
总结:
排序算法
public class BubbleSortTest {
public static void main(String[] args) {
int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
//冒泡
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
System.out.println();
//冒泡排序,实现数据元素从小到大排序
for (int j = 0; j < arr.length-1; j++) {
for(int i = 0; i<arr.length-1-j;i++){
if(arr[i] > arr[i+1]){
//交换arr[i]和arr[i+1]
int temp = arr[i];
arr[i] = arr[i+1];
arr[i + 1] = temp;
}
}
}
System.out.println();
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
定义了一个基准值pivot,有两个指针,一个从数组的从前往后指,另外一个从后往前指,从前往后走,找到的第一个low比pivot大的,就停下来,high从后往前走,找到第一个比pivot小的就停下来,交换low与high,按照当前的索引,继续执行上述操作
第一轮操作:跟n的复杂度是同阶的,时间复杂度为O(n)
第二轮操作同理
排序算法性能对比
各种内部排序方法性能比较
排序算法的选择
Arrays工具类的使用
数组工具类Arrays的使用(熟悉) 1.Arrays类所在位置:处在java.util包下 2.作用: java.util.Arrays类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。public class ArrayTest { public static void main(String[] args) { //1.boolean equals(int[]a,int[]b):比较两个数组的元素是否依次相等 int[] arr1 = new int[]{1,2,3,4,5}; int[] arr2 = new int[]{1,2,3,4,5}; System.out.println(arr1 == arr2); //false boolean isEquals = Arrays.equals(arr1,arr2); System.out.println(isEquals); //true //2.String toString(int[] a):输出数组元素信息。 System.out.println(arr1); //[I@4eec7777 System.out.println(Arrays.toString(arr1)); //[1, 2, 3, 4, 5] //3.void fill([] a,int val):将指定值填充到数组之中。 Arrays.fill(arr1, 10); System.out.println(Arrays.toString(arr1)); //[10, 10, 10, 10, 10] //4. void sort(int[] a):使用快速排序算法实现的排序 int [] arr3 = new int[]{34,54,3,2,65,7,34,5,76,34,67}; Arrays.sort(arr3); System.out.println(Arrays.toString(arr3)); //[2, 3, 5, 7, 34, 34, 34, 54, 65, 67, 76] //5.int binarySearch(int[] a,int key):二分查找 // 使用前提:当前数组必须是有序的 int index = Arrays.binarySearch(arr3,15); if(index >= 0){ System.out.println("找到了,索引位置为:" + index); }else{ System.out.println("未找到"); } System.out.println(index); //-5,未找到 } }
数组使用中的常见异常
1.数组的使用中常见的异常小结 数组角标越界的异常:ArrayIndex0ut0fBoundsException 空指针的异常:NullPointerException 2.出现异常会怎样?如何处理? > 一旦程序出现了异常,代码就会终止执行 > 针对于异常提供的信息,修改对应代码,避免异常再次出现public class ArrayExceptionTest { public static void main(String[] args) { //1.数组角标越界的异常: int[] arr = new int[10]; //角标的有效范围:0,1,2,3,...,9 // System.out.println(arr[10]); // System.out.println(arr[-1]); // 2.空指针异常: //情况1: // int[] arr1 = new int[10]; // arr1 = null; // System.out.println(arr1[0]); //0 //情况2: // int[][] arr2 = new int[3][]; // arr2[0] = new int[10]; // 此行代码不存在时,下一行代码出现NullPointerException // System.out.println(arr2[0][1]); //NullPointerException //情况3: // String[] arr3 = new String[4]; // System.out.println(arr3[0].toString()); //NullPointerException } }