我在输入知识,也在用我理解后的方式进行输出
以下内容是 兔C 献给大家的 2022年1月1日 的 新年礼物
文章目录- 1. 数组的概念
- 1.1关于兔C残篇
- 1.2 关于什么是数组
- 1.3 图解 变量和数组的区别
- 2. 数组的定义语法
- 3. 数组在内存中的状态
- 3.1 什么是栈
- 3.2 什么是堆
- 3.3 图解 数组在内存中的状态
- 4. 数组的初始化
- 4.1 静态初始化
- 4.2 动态初始化
- 4.3 数组的默认初始化
- 4.4 默认初始化的概念:
- 4.5 数组元素的默认值
- 4.6 隐式和显示的概念
- 5. 数组的使用
- 5.1 关于数组使用上的概念认识
- 5.2 数组元素的赋值存储
- 5.3 数组元素中存储的数据取出
- 5.4 数组下标越界异常
- 6. 数组的特点
- 7. 数组练习题
- 7.1 寻找数组中的最大值
- 7.2 补充:增强for循环
- 7.3 数组作为参数
- 7.4 反转数组
- 8. 多维数组
- 8.1 图解
- 8.2 多维数组的静态初始化
- 8.3 多维数组的动态初始化语法
- 8.4 使用for循环输出数组中所有元素
- 9. Java.util.Arrays 类
- 9.1 .toString(); 方法
- 9.2 .sort(); 方法
- 9.3 .fill 方法填充数组中的元素
- 10. 冒泡排序
- 11. 稀疏数组
- 11.1 需求
- 11.2 需求分析及解决方案
- 11.3 稀疏数组的概念
- 11.4 需求实现
- 11.5 将稀疏数组还原成普通数组
我们先用理解的形式说明一下什么是数组:
1.1关于兔C残篇我们之前的残篇中提到过一个概念,就是java中的数据类型,分为两种,基本数据类型和引用数据类型,我们在兔C残篇方法的讲述中提到过,方法的返回值可以用基本数据类型,但是没有跟大家提到过引用数据类型,是因为我们兔C残篇还没有进展到面向对象的阶段,兔C残篇在现阶段,先进行java SE的相关知识输出。
1.2 关于什么是数组回到话题,什么是数组,我们知道基本数据类型有,byte short int long float double char boolean。我们在使用这些数据类型声明变量的时候,都是一个变量一个变量进行声明的,可是如果我们的变量都是相同类型的声明呢?比如 我们需要声明10个int类型的变量,那这时候我们一个一个进行声明么?不! 我们可以用到数组,数组就可以帮我们存储10个相同类型的数据,不在需要变量来一个一个存储。
1.3 图解 变量和数组的区别//变量 声明在栈中
//数组 声明在栈中,并通过存储的地址值指向了堆,在堆中开辟了空间
// 数据类型[] 数组名称 = new 数据类型[]; // 参上,是数组在java中的定义语法。其中的含义,我们接下来进行说明 // 我们可以先声明一个数组的类型 int[] array; //这就是声明了一个int类型的数组,名称为array //但是还不能使用,因为我们还没有进行实例化,数组也是引用类型的。 array = new int[10]; //这里我们进行了数组的实例化,为其开辟了一块内存空间,而空间的状态为10个大小 //这里我们说明一个问题,我们经常看到其他人在声明数组的时候,会把[] 放在不同的位置,有的人放在了声明的类型后面,有的人写在了数组名后面,我们这里来进行说明 //[] 号的抒写位置,没有对错的区分 int[] array = new int[]; //括号放在数据类型的后面,是java 的标准写法。 int array[] = new int[]; //括号放在数组名称后面,是c和c++中的抒写风格。 //探其原因是因为,让早期的程序员更能适应新生的java 语言 //参上有一个问题,就是 12行 和 13行的代码,只是为了演示和说明,并没有设置初始化的容量大小,这里一定要切记,数组的初始化创建时候,必须声明初始容量的大小。
以上代码块中的注释,不难理解,可能发到博文上的注释,没有再typora上的视觉舒适,但是其注释内容容易理解,这里也只是说明了数组的创建语法,还有不同语法声明的区别。
文章进行到这里,我们的程序在编译器中的状态应该是,大家都声明出了数组,int array[] = new int[10];
但是数组怎么用,数组相关的理论知识呢? 我们接下来为大家逐一揭晓。
我们既然有了数组,那我们来先来看看数组在内存中的状态,在堆和栈中的状态。还有什么是堆,什么是栈?我们也先来一个铺垫。
3. 数组在内存中的状态 3.1 什么是栈基本数据类型:当创建一个基本数据类型的变量时,会存放于栈中,而且会包含其具体的数据值。
引用数据类型:存放引用数据类型时,存放的是当前对象在堆里面的地址值
3.2 什么是堆使用 new 关键字进行实例化的,都会进入到堆当中开辟内存空间,并且会有一个地址值,该地址值保存在栈中引用他的名称中。
3.3 图解 数组在内存中的状态当我们编写代码时,比如声明一个数组,int array[];
这里我们并没有进行初始化,所以数组的默认值也是null,但是此时在内存中的状态呢?
因为只是声明了数组,并没有进行初始化,所以内存中也只是在栈中压入了一个array对象
而当我们为数组初始化之后,array = new int[5];
此时就会在堆中开辟空间,并且这块空间会被分割成5个小份,同时栈中的array也会指向这块内存空间
4. 数组的初始化现在我们知道了数组的语法,就是怎么样声明一个数组,还知道了语法上的抒写区别,然后还有数组声明过程中在栈和堆中的状态,也知道了数组的类型是引用类型,最后还有数组和基本数据类型创建变量时 在内存当中的区别。
说完了这些,我们在聊一下数组的初始化方式,然后说完初始化方式,我们就开始聊数组上使用方面的话题。
4.1 静态初始化//静态初始化,就是创建数组,在其实例化时为其定义好具体的存储数据值 int array[] = {1,2,3,4,5}; //这里就是用静态初始化,声明了一个空间大小为5且数据值为1,2,3,4,5的数组4.2 动态初始化
//动态初始化,就是创建数组,在其实例化时,只声明该数组的大小 int array[] = new int[5]; //然后在使用的时候,在为其赋具体值4.3 数组的默认初始化
int array[] = new int[5]; //动态初始化,也是默认的初始化方式4.4 默认初始化的概念:
首先我们需要知道,我们的数组是引用类型的,它的元素相当于类的实例变量,然后也因此数组一旦分配内存空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化了。
4.5 数组元素的默认值说完默认初始化的概念,我们在给大家科普一下数组的默认值,当我们创建一个int类型的数组,然后声明了数组空间的大小,如果此时声明是用的动态初始化的方式,声明之后没有赋值,那么没有赋值的元素默认值就为0。同样如果是String类型的话,那默认值就是null。
说到这还是补充一下吧,我们知道数组是引用类型的,那如果我们声明数组的时候,并没有进行实例化,那么数组的默认值是什么? 也为null!
4.6 隐式和显示的概念这里的隐式就相当于我们在声明数组初始化容量大小时,没有给其中元素赋具体的值,然后会自动默认的有一个默认值,那显示是相对的,当我们需要使用存储数据,也就是给其中元素赋值时,就是显示的。
5. 数组的使用 5.1 关于数组使用上的概念认识那说完了数组的基础概念,我们来说一下关于数组的使用:
这里我依然首先要知道的概念是,数组是有元素下标的,也就是初始化设置容量大小时,容量中的每个元素都有一逐一对应的下标值,那数组的下标是从0开始的,也就是说,比如设置的容量大小为5,那下标的顺序就是:0,1,2,3,4。那我们如何为其中的下标对应的元素赋值呢?
5.2 数组元素的赋值存储int array[] = new int[5]; array[0] =10; array[1] =20; array[2] =30; array[3] =40; array[4] =50;
为什么标题写成了数组元素的赋值存储,因为存储的一组int数据类型中,其中的每一个元素,都相对于是一个变量。
5.3 数组元素中存储的数据取出int array[] = new int[5]; //取出数组的元素我们可以直接利用下标值 //例如,我们想看到数组中下标元素为3 存储的数据是否为 40 System.out.println("值是多少呢? "+ array[3]); //指定取出 //如果我们想取出整个数组中的元素,我们可以使用for循环 for(int i =0; i5.4 数组下标越界异常 上面的for循环中,我们已经写上了注释声明,那如果取值范围超出数组的下标了呢?
比如现在我们存储了5个元素,那对应的下标是:0,1,2,3,4
如果我们偏偏取值 array[5]; 就会报出错误信息:java.lang.ArrayIndexOutOfBoundException 提示我们出现了数组下标越界异常,一般出现此错误,就是因为我们的取值时超出了存储的范围。
6. 数组的特点7. 数组练习题
- 数组的长度是在创建时需要指定的,所以数组一旦被创建,就会在方法栈,方法堆中声明出对应的信息,比如声明在方法栈当中的对象名,存储用于指向方法堆当中具体实例化的空间内存地址值,比如方法堆中,会开辟出内存空间,空间中又会分割出小的空间来存储具体的值。
- 声明出来的数组一定是用于存储一组相同数据类型的数据。
- 数组可以存储基本数据类型,也可以是引用数据类型。只要是同一组相同的数据即可。
- 数组属于引用类型,数组也可以看成是对象,数组中的每个元素,相当于该对象的成员变量。
- 数组本身就是对象,java 的对象都是在堆中的,因此无论是用数组存储基本数据类型,还是引用数据类型,数组对象本身是在堆当中的。
- 数组是有序类型的,它的顺序是按照我们存储的顺序排序的。
//在这里我们先定义一个数组,然后在定义一个变量,然后以下的demo都使用此数组和变量
int array[] = {1,2,3,4,5}; int number = array[0];7.1 寻找数组中的最大值for(int i =0; i< array.length; i++){ if(array[i] > number){ number = array[i]; } } System.out.println("数组中的最大值为:" +number);7.2 补充:增强for循环for(int arrays : array){ //第一个参数相当于数组的元素,第二个参数相当于数组 //增强for循环是 jdk1.5以后的新特性,它没有下标,所以适合打印输出,不适合 *** 作元素 System.out.println(arrays); } //切记,增强for循环,没有下标,它无法 *** 作元素7.3 数组作为参数另外,数组也可以作为方法的参数
代码示例:
public static void main(String[] args){ int array[] = {1,2,3,4,5}; printArray(array); } public static void printArray(int[] array){ for(int arrays : array){ System.out.println("元素值为;"+ arrays); } }7.4 反转数组这里我们写一个反转数组元素的democode,并把数组作为方法的返回值
public class demoFortoArray{ public stativ void main(String[] args){ //我们先在主程序中定义一个数组,用于后面反转的 *** 作 int array[] ={1,2,3,4,5}; //这里调用反转数组元素的方法 int[] ints = toArray(array); //因为方法的返回值是 int[] 类型,所以会返回一个int类型的数组 } //我们写一个反转数组元素的方法 public static int[] toArray(int[] array){ //我们定义一个用于存储反转后元素的数组,数组的长度等于 被传入到方法中的参数 int result[] = new int[array.length]; //int result[] ={array.length}; //i的下标,是被传入的数组下标,j的下标是我们方法体中数组的下标 for(int i = 0,j = result.length -1; i < array.length; i++ ,j--){ result[j] = array[i]; } //这里进行返回 resurn result; } //定义一个打印输出数组元素的方法 public static void printArray(int[] array){ for(int i=0; i< array.length; i++){ System.out.println("当前元素的参数值为:"+array[i]); } } }8. 多维数组多维数组的概念其实很好理解,比如我们现在的数组是一个数组,而这个数组的理论知识我们都已经掌握,那多维数组就是在一个数组的维度上嵌套了一层数组,也就是说一个普通数组的元素中,包含了下层维度的数组。
8.1 图解 8.2 多维数组的静态初始化//我们用code写一个 三行两列的demo int array[][] = {{1,2},{3,4},{5,6}; //如何取得二维数组中的元素呢? //我们现在知道了二维数组,就是一维数组中的元素嵌套存储了一层数组的概念 //所以:: array[0]; //这是取得第一个数组的地址值 array[1]; //这是取得第二个数组的地址值 array[2]; //这是取得第三个数组的地址值 //我们也可以使用for循环,取得array[0]中的元素 //直接使用增强for,我们说过增强for适合打印输出,不适合 *** 作元素 for(int arrays : array[0]){ System.out.println(arrays); } //使用普通for循环打印 for(int i =0; i< array[0].length;i++){ System.out.println(array[0][i]); } //那如果我们单独获取 二维数组维度中指定的值呢? // 例如:需求(两个需求): 指定获取 1 指定获取 2 System.out.println(array[0][0]); System.out.println(array[0][1]);8.3 多维数组的动态初始化语法int array[][] = new int[4][2]; //赋值动作 array[0][0] =1; array[0][1] =2; array[1][0] =3; array[1][1] =4; //以此类推8.4 使用for循环输出数组中所有元素int array[][] ={{1,2},{3,4},{5,6}}; //我们先用循环,设置出外层的数组 for(int i =0; i 9. Java.util.Arrays 类我们创建数组之后,有一个 .length 长度属性,来提供给我们 *** 作数组的便捷,那如果我们想对数组有更多的 *** 作呢?这时候 Arrays 工具类中,为我们提供出了一些相对的方法。这里我们举例某些常用方法。
9.1 .toString(); 方法//我们用此方法可以得到数组中元素内容为String类型,然后用其输出。 int array[] = {1,2,3,4,5,6,7,8,9}; String tSarray = Arrays.toString(array); System.out.println(tSarray);9.2 .sort(); 方法//我们可以使用sort方法按照升序顺序排序数组中的元素内容 int array[] = {9,3,6,1,2,8,4,7,10,5}; Arrays.sort(array); //经过排序之后,我们在使用toString方法输出元素内容 String tSarray = Arrays.toString(array); System.out.println(tSarray);9.3 .fill 方法填充数组中的元素//我们可以使用file方法,填充数组中的元素内容 int array[] = {1,2,3,4,5}; //例如我们都将其填充为0值 Arrays.fill(array,0); String tSarray = Arrays.toString(array); //它还提供了重载方法,指定填充某些元素 Arrays.fill(array,0,2,0); //0是起始下标位置,2为结束下标位置,0将其填充的目标值10. 冒泡排序冒泡排序,是最为出名的一种排序算法,总共有八大排序!
public class MpSort{ public static void main(String[] args){ int array[] = {10,6,2,9,4,3,8,1,7,5}; int[] ints = toMpArray(array); String tsArray = Arrays.toString(ints); System.out.println(tsArray); } public static int[] toMpArray(int[] array){ //空罐子 int temp =0; //定义外层循环,用于控制冒泡的排序轮数 for(int i=0; i < array.length; i++){ //定义内层循环,用于比较和交换元素的位置 for(int j =0; j < array.length -1-i; j++){ //-i 是减去已比较过的元素 -1是下标的范围,不能超过数组的范围 //比较元素 if(array[j+1] < array[j]){ //j+1是下一个元素的下标 temp = array[j]; array[j] = array[j+1]; array[j+1] =temp; } } } return array; } }//利用flag标志,控制程序,实现冒泡
public class MpSort{ public static void main(String[] args){ int array[] = {10,6,2,9,4,3,8,1,7,5}; int[] ints = toMpArray(array); String tsArray = Arrays.toString(ints); System.out.println(tsArray); } public static int[] toMpArray(int[] array){ //空罐子 int temp =0; boolean flag =false; //通过flag标识位减少没有意义的比较 //定义外层循环,用于控制冒泡的排序轮数 for(int i=0; i < array.length; i++){ //定义内层循环,用于比较和交换元素的位置 for(int j =0; j < array.length -1; j++){ //-i 是减去已比较过的元素 -1是下标的范围,不能超过数组的范围 //比较元素 if(array[j+1] < array[j]){ //j+1是下一个元素的下标 temp = array[j]; array[j] = array[j+1]; array[j+1] =temp; flag = true; } } //如果定义的标志为false,说明没有走上面的循环,直接跳出 if(flag == false){ break; } } return array; } }11. 稀疏数组稀疏数组,是一种数据结构。
11.1 需求如果我们模拟一个五子棋的小程序,该程序具有存盘退出和续上盘的功能,而我们用数组进行存储。
我们想象一下五子棋棋盘的样子,那我们用0表示可以落子的棋盘格子,用1代表一个颜色的棋子,用2代表另一个颜色的棋子,那我们如何解决呢?
11.2 需求分析及解决方案如果用二维数组的话,那也会存储很多个0,设置好棋盘的可以落子的格格,那这么多个0需要存储,我们有没有更好的解决办法呢?我们可以使用压缩算法,将数据量变少,也就是使用稀疏数组。
11.3 稀疏数组的概念当一个数组中大部分元素为重复元素,或者为同一值的数组时,可以采用稀疏数组来保存该数组。
11.4 需求实现
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
public class xsArray{ public static void main(String[] args){ //1.创建一个二维数组, 11*11 //0:表示没有棋子,1:表示黑色棋子,2:表示白色棋子 int array[][] = new int[11][11]; //11行11列 棋盘格子 //坐标,1行2列的位置,落黑棋 array[1][2] = 1; //坐标, 1行3列的位置,落黑棋 array[1][3] = 1; //打印数组元素 for(int arrays: arrys){ for(int ints : arrays){ System.out.print(ints): } } //转换为稀疏数组进行保存 //1.获取有效值的个数 int sum =0; for(int i =0; i < 11; i++){ for(int j =0; j < 11; j++){ if(array[i][j]!=0){ sum++; } } } System.out.println("有效值的个数:"+sum); //2.创建一个稀疏数组 int[][] arrays = new int[sum+1][3]; //[此处为有效元素的行数][此处为列的元素(行;列;值,所以是3)] arrays[0][0] = 11; //行 arrays[0][1] = 11; //列 arrays[0][2] = sum; //值 //3.遍历二维数组,将非0的值,存放到稀疏数组当中 int count =0; for(int i =0; i < array.length; i++){ for(int j = 0; j < array[i].length; j++){ count++; //开始设置存放到稀疏数组 arrays[count][0] = array[i]; arrays[count][1] = array[j]; arrays[count][2] = array[i][j]; } } //4.输出稀疏数组 for(int i = 0 ; i < arrays.length; i++){ System.out.println( arrays[i][0] +"t" + arrays[i][1] +"t" + arrays[i][j] +"t" ); } //打印出来的值,是记录棋盘位置的棋子坐标 } }11.5 将稀疏数组还原成普通数组//读取稀疏数组 int[] arrayt = new int[arrays[0][0],arrays[0][1]]; //行和列的坐标 //还原其中元素的值 for(int i = 1; i < arrays.length; i++){ arrayt[arrays[i][0]][arrays[i][1]] = arrays[i][2]; } //打印还原后的元素值 for(int arrays: arryt){ for(int ints : arrays){ System.out.print(ints): } }欢迎分享,转载请注明来源:内存溢出
评论列表(0条)