数组20241226
[数组详情](深入理解 Java 数组 - 静默虚空 - 博客园)
什么是数组:
数组是相同类型数据的有序集合
注意:必须是相同数据
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成其中,每一个数据称作一个数组元素。
每个数组元素可以通过一个下标来访问它们.
类似创建了一个足球队数组,通过号码来对应球员数组的内存模型
数组是存储多个相同类型变量的对象。数组的所有元素保存在堆内存中==
•数组创建后立即拥有默认值。
•索引从0开始。graph LR A[Java内存]==>B[堆] A[Java内存]==>C[栈] A[Java内存]==>D[方法区] B[堆]==>E[存放new的对象和数组] B[堆]==>F[可以被所有的线程共享,不会存放别的对象引用] C[栈]==>G[存放(8种)基本变量类型(会包含这个基本类型变量的具体的值)] C[栈]==>H[引用对象的变量(会存放这个引用在堆里面的具体地址)] D[方法区]==>I[可以被所有的线程共享] D[方法区]==>J[包含了所有的class和static变量]数组的声明和创建
两种声明方式
- 数组类型[] 数组名 //首选这种,第二种是迎合C语言
- 数组类型 数组名[]
数组的定义
1.数组类型 [] 数组名 = new 数组类型[数组长度] (常规定义)
int[] numbers01 = new int[10]; float[] numbers02 = new float[5];
2.数组类型 数组名[ ] = {元素1,元素2,…}
int[] number03 ={1,2,4,7,87}; float[] number04 ={1.0,32.3,23.6,7.2}
注意
int[] a; a = new int[5] ;
等同于
int[] a = new int[5];
数组中的常见异常
// 异常一:数组没有创建 int a[] = null; a[0] = 1; System.out.println(a[0]);
输出空指针报错:
java.lang.NullPointerException
Exception in thread "main" java.lang.NullPointerExceptionat com.pangHuHuStudyJava.arrays.Demo02.main(Demo02.java:6)
// 异常二:下标越界 int a[] = { 1, 2, 3 }; System.out.println(a[3]);
输出数组指针越界!
java.lang.ArrayIndexOutOfBoundsException
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5at com.pangHuHuStudyJava.arrays.Demo02.main(Demo02.java:8)
动态初始化(先定义再赋值)第9到第18行
package com.pangHuHuStudyJava.arrays; import java.sql.SQLOutput; //数组的创建、计算数组所有元素之和 public class Demo01 { public static void main(String[] args) {int[] numbers01;numbers01 = new int[10];//定义数组 //等于 int[] numbers01=new int[10];//给数组赋值 动态初始化numbers01[0] = 1;numbers01[1] = 2;numbers01[2] = 3;numbers01[3] = 4;numbers01[4] = 5;numbers01[5] = 6;numbers01[6] = 7;numbers01[7] = 8;numbers01[8] = 9;numbers01[9] = 10;//直接赋值//用array.length 来输出下数组的最大值和求和float[] numbers02 = new float[5];定义数组 //等于 int[] numbers01=new int[10];double[] numbers03 = {12.2,3.2,5.2,312.3,2,23.2,332.2,4455.2};//直接定义double max=0;//请一定注意 局部变量在使用前无比赋明确的初值double sum=0 ;//请一定注意 局部变量在使用前无比赋明确的初值for (int i = 0; i < numbers03.length; i++) {max = numbers03[i];sum += numbers03[i];if(max < numbers03[i]){max=numbers03[i];}}System.out.println("数组三的最大值:"+max);System.out.println("数组三的和:"+sum); } }
输出:
数组三的最大值:4455.2 数组三的和:5145.5
数组的三种初始化方式
1.静态初始化:
int[] number03 ={1,2,4,7,87}; float[] number04 ={1.0,32.3,23.6,7.2}
2.动态初始化(包含默认初始化)
int[] numbers01=new int[10];//给数组赋值 动态初始化numbers01[0] = 1;numbers01[1] = 2;numbers01[2] = 3;numbers01[3] = 4;numbers01[4] = 5;numbers01[5] = 6;
数组的四个基本特点
其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
其元素必须是相同类型,不允许出现混合类型。
数组中的元素可以是任何数据类型,包括基本类型和引用类型数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型数组对象本身是在堆中的。
数组的边界
下标的合法区间:[0,length-1] 如果越界就会报错
java.lang.ArrayIndexOutOfBoundsException
◆小结:
数组是相同数据类型(数据类型可以为任意类型)的有序集合数组也是对象。
数组元素相当于对象的成员变量
数组长度的确定的,不可变的。如果越界,则报:
ArrayIndexOutofBounds
数组的使用
1.简单for +array.length
2.增强型for循环 实现一个数组翻转
package com.pangHuHuStudyJava.arrays; import java.util.Arrays; // 数组的使用:增强型 for 循环 // 本程序实现了数组的反转,并打印原始数组和反转后的数组 public class Demo03 {public static void main(String[] args) {// 定义一个数组并静态初始化int[] numbers = {7, 3, 6, 11, 43, 1, 10, 4, 21, 10}; // 获取数组的长度int count = numbers.length; // 定义一个新的数组,用于存储反转后的数组int[] numberCopy = new int[count]; // 使用 for 循环将原数组的元素从后往前赋值到新数组中for (int i = 0; i < count; i++) {numberCopy[i] = numbers[count - i - 1]; }// 输出原始数组的元素System.out.println("原始数组的元素为:"); for (int number : numbers) { // 使用增强型 for 循环遍历数组System.out.print(number + " "); }// 输出反转后的数组元素System.out.println("\n反转后数组的元素为:"); for (int number : numberCopy) { // 使用增强型 for 循环遍历反转后的数组System.out.print(number + " "); }} }
如果需要更简洁的方式,可以直接使用
Arrays.toString()
打印数组内容:System.out.println("原始数组的元素为:" + Arrays.toString(numbers)); System.out.println("反转后数组的元素为:" + Arrays.toString(numberCopy));
这会直接将数组的所有元素以字符串形式输出,例如:
原始数组的元素为:[7, 3, 6, 11, 43, 1, 10, 4, 21, 10] 反转后数组的元素为:[10, 21, 4, 10, 1, 43, 11, 6, 3, 7]
改进下:做一个函数封装,这里涉及一个数组的返回,C有一个返回的数组名(数组的地址)
package com.pangHuHuStudyJava.arrays; // 对 Demo03 的功能进行函数封装,增加代码复用性 // 本程序实现了数组反转功能,并通过函数返回反转后的数组 public class Demo04 {public static void main(String[] args) {// 定义一个数组并静态初始化int[] numbers = {7, 3, 6, 11, 43, 1, 10, 4, 21, 10};// 调用封装好的函数 arrayFlip 对数组进行反转,并打印反转后的数组元素for (int i : arrayFlip(numbers)) { // 直接使用增强型 for 循环输出反转结果System.out.print(i + " ");}}/*** 定义一个静态方法,用于反转数组** @param array 传入的整型数组* @return 返回反转后的数组*/public static int[] arrayFlip(int[] array) {// 获取数组长度int count = array.length;// 创建一个新数组用于存放反转结果int[] result = new int[count];// 使用循环将原数组从后往前赋值到新数组中for (int i = 0; i < count; i++) {result[i] = array[count - 1 - i];}// 返回反转后的数组return result;} }
chatgpt 改进:
减少不必要的数组复制
如果允许直接修改原数组,可以省去创建新数组的开销: 注意这里直接把原数组翻转!!!
public static void arrayFlipInPlace(int[] array) {int left = 0,;int right = array.length - 1;while (left < right) {int temp = array[left];array[left] = array[right];array[right] = temp;left++;right--;}return array; }
多维数组、Array(sort fill binarySearch)方法20241226
多维数组定义、赋值、理解
二维数组定义与初始化:
- 动态初始化:先定义数组大小,然后逐个赋值。
- 静态初始化:直接定义并赋值,适用于已知数据的场景。
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
二维数组
int\[][] a[][]= new int\[2][5]
;理解:
三维数组 numbers02[2][6][5]
遍历二维数组:
- 增强 for 循环:适合简单遍历,不关心索引时使用。
- 标准 for 循环:适合需要操作索引或灵活控制遍历时使用。
使用
Arrays.toString()
:
Arrays.toString(array)
用于将一维数组转换为字符串格式,方便输出。package com.pangHuHuStudyJava.arrays; import java.util.Arrays; // 引入 Arrays 工具类 // 多维数组的定义、赋值与展示,使用增强 for 循环和标准 for 循环 public class Demo05 {public static void main(String[] args) {// 定义一个 2x2 的二维数组,并动态初始化int[][] numbers = new int[2][2]; numbers[0][0] = 1; // 为二维数组的第 0 行第 0 列赋值numbers[0][1] = 2; // 为二维数组的第 0 行第 1 列赋值numbers[1][0] = 3; // 为二维数组的第 1 行第 0 列赋值numbers[1][1] = 4; // 为二维数组的第 1 行第 1 列赋值// 使用静态初始化方式定义一个二维数组int[][] numbers02 = {{1, 2, 5}, {3, 4, 6}};// 增强 for 循环遍历二维数组System.out.println("增强 for 循环遍历二维数组");for (int[] ints : numbers02) { // 遍历每一行for (int anInt : ints) { // 遍历当前行的每个元素System.out.print(anInt + " "); // 输出当前元素}System.out.println(); // 换行}System.out.println("=========================");// 标准 for 循环遍历二维数组System.out.println("标准 for 循环遍历二维数组");for (int i = 0; i < numbers02.length; i++) { // 遍历每一行for (int j = 0; j < numbers02[i].length; j++) { // 遍历当前行的每个元素System.out.print(numbers02[i][j] + " "); // 输出当前元素}System.out.println(); // 换行}System.out.println("=============");// 使用 Arrays 类中的方法将二维数组的每一行转换为字符串System.out.println("使用 Arrays 类中的方法实现 toString");for (int i = 0; i < numbers02.length; i++) { System.out.print(Arrays.toString(numbers02[i]) + " "); // 将当前行转为字符串并输出System.out.println(); // 换行}} }
增强 for 循环遍历二维数组 1 2 5 3 4 6 ========================= 标准 for 循环遍历二维数组 1 2 5 3 4 6 ============= 使用 Arrays 类中的方法实现 toString [1, 2, 5] [3, 4, 6]
掌握
Arrays
工具类的常用方法,如toString()
和deepToString()
(用于打印多维数组)。
Arrays.deepToString()
是 Java 提供的一个工具方法,用于将多维数组的内容转换为字符串格式。与Arrays.toString()
不同,它可以处理多维数组,并递归地对所有嵌套数组进行字符串化。public static String deepToString(Object[] array)
功能
- 将多维数组的每个元素(包括嵌套的数组)转换为字符串。
- 生成的字符串格式类似于嵌套的方括号结构
[[], []]
,表示数组的层级。与
toString()
的区别
Arrays.toString()
:
- 仅支持一维数组。
- 如果传入多维数组,会直接输出对象的内存地址,如
[I@5e91993f
。Arrays.deepToString()
:
- 支持多维数组。
- 递归遍历所有嵌套数组,输出层级结构。
示例对比:
int[][] numbers = {{1, 2, 3}, {4, 5, 6}}; System.out.println(Arrays.toString(numbers)); // 输出:[[I@5e91993f, [I@1c4af82c] System.out.println(Arrays.deepToString(numbers)); // 输出:[[1, 2, 3], [4, 5, 6]]
作业:
◆ 具有以下常用功能:
给数组赋值:通过fill
方法。
对数组排序:通过sort
方法,按升序。
比较数组:通过equals
方法比较数组中元素值是否相等
deepToString()
将多维数组的每个元素(包括嵌套的数组)转换为字符串。◆查找数组元素:通过
binarySearch
方法能对排序好的数组进行二分查找法操作。package com.pangHuHuStudyJava.arrays; import java.util.Arrays; //熟悉Arrays类各种方法:deepToString, fill, sort, equals, binarySearch //重点演示:deepToString 将多维数组的每个元素(包括嵌套的数组)转换为字符串,生成的字符串格式类似于嵌套的方括号结构 `[[], []]` public class Demo06 {public static void main(String[] args) {// 使用 deepToString 方法输出二维数组System.out.println("deepToString 输出二维数组:");// 定义一个二维数组 numbers[3][3]int[][] numbers = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};// 打印二维数组的内容System.out.println(Arrays.deepToString(numbers));// 定义一个三维数组 numbers02[2][3][5]int[][][] numbers02 = {{{4, 2, 4, 5, 6},{12, 3, 5, -2, 4},{23, 32, 5, 45, 65}},{{1, 2, 3, 4, 5},{6, 7, 8, 9, 10},{11, 12, 13, 14, 15}}};// 使用 deepToString 方法输出三维数组System.out.println("deepToString 输出三维数组:");System.out.println(Arrays.deepToString(numbers02));} }
deepToString 输出二维数组: [[1, 2, 3], [4, 5, 6], [7, 8, 9]] deepToString 输出三维数组: [[[4, 2, 4, 5, 6], [12, 3, 5, -2, 4], [23, 32, 5, 45, 65]], [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]]]
Arrays.sort方法
package com.pangHuHuStudyJava.arrays; import java.util.Arrays; //熟悉Arrays中的方法 fill sort public class Demon07 {public static void main(String[] args) {int[] numbers = {2, 5, 10, 12, -23, 3, 76, 231, 435, -234, 65};System.out.println("原始数组:" + Arrays.toString(numbers));Arrays.sort(numbers);System.out.println("排序(正序)后数组:" + Arrays.toString(numbers));//倒序有点问题 要用到自定义比较器/* Integer[] array = {1, 3, 2, 5, 4};//这里使用的是 Integer[],而不是 int[],因为 Comparator 只支持对象类型// 使用自定义比较器实现倒序Arrays.sort(array, (a, b) -> b - a);*///所以我自己再写一个倒序(正序再翻转就行了)arrayReverse(numbers);//正序后再翻转,实现倒序System.out.println("排序(倒序)后数组:" + Arrays.toString(numbers));}public static void arrayReverse(int[] array){//这种方法时间复杂度为 O(n)O(n)O(n),空间复杂度为 O(1)O(1)O(1),非常高效。int left=0;int right= array.length-1;while(left<right){int temp = array[left];array[left] = array[right];array[right] = temp;left++;right--;}} }
输出结果:
原始数组:[2, 5, 10, 12, -23, 3, 76, 231, 435, -234, 65] 排序(正序)后数组:[-234, -23, 2, 3, 5, 10, 12, 65, 76, 231, 435] 排序(倒序)后数组:[435, 231, 76, 65, 12, 10, 5, 3, 2, -23, -234]
Array.fill方法
package com.pangHuHuStudyJava.arrays; import java.util.Arrays; public class Demo08 {public static void main(String[] args) {// 示例 1:整体填充int[] array1 = {2, 5, 10, 12, -23, 3, 76, 231, 435, -234, 65};System.out.println("原始数组 array1:" + Arrays.toString(array1));// 将整个数组填充为 0Arrays.fill(array1, 0);System.out.println("执行 Arrays.fill(array1, 0) 后的数组:" + Arrays.toString(array1));System.out.println("------------------------------------------------");// 示例 2:部分区间填充int[] array2 = {2, 5, 10, 12, -23, 3, 76, 231, 435, -234, 65};System.out.println("原始数组 array2:" + Arrays.toString(array2));// 填充区间 [1, 4) 的元素为 666Arrays.fill(array2, 1, 4, 666);System.out.println("执行 Arrays.fill(array2, 1, 4, 666) 后的数组:" + Arrays.toString(array2));} }
输出结果:
原始数组 array1:[2, 5, 10, 12, -23, 3, 76, 231, 435, -234, 65] 执行 Arrays.fill(array1, 0) 后的数组:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ------------------------------------------------ 原始数组 array2:[2, 5, 10, 12, -23, 3, 76, 231, 435, -234, 65] 执行 Arrays.fill(array2, 1, 4, 666) 后的数组:[2, 666, 666, 666, -23, 3, 76, 231, 435, -234, 65]
Arrays.binarySearch方法
package com.pangHuHuStudyJava.arrays; import java.util.Arrays; // 使用 binarySearch 方法查找数组中的数 public class Demo09 {public static void main(String[] args) {int[] numbers = {2, 5, 10, 12, -23, 3, 76, 231, 435, -234, 65};System.out.println("原始数组:" + Arrays.toString(numbers));// 在查找之前必须排序数组Arrays.sort(numbers);System.out.println("排序后的数组:" + Arrays.toString(numbers));// 查找数值 5 的位置int[] target ={-666,4,10000};calbinarySearch(numbers,target);}public static void calbinarySearch(int[] array,int[] target) {//请确保 传入的array 是排好序的数组for (int i : target) {int result = Arrays.binarySearch(array, i);if (result >= 0) {System.out.println("数值 " + i + " 在数组中的索引为:" + result);} else {System.out.println("数值 " + i + " 不存在,返回值为:" + result);int insertionPoint = -(result + 1);System.out.println("如果插入,数值 " + i + " 应插入到索引位置:" + insertionPoint);}}} }
原始数组:[2, 5, 10, 12, -23, 3, 76, 231, 435, -234, 65] 排序后的数组:[-234, -23, 2, 3, 5, 10, 12, 65, 76, 231, 435] 数值 -666 不存在,返回值为:-1 如果插入,数值 -666 应插入到索引位置:0 数值 4 不存在,返回值为:-5 如果插入,数值 4 应插入到索引位置:4 数值 10000 不存在,返回值为:-12 如果插入,数值 10000 应插入到索引位置:11