兔C残篇:如何快速掌握 Java数组 (多维度剖析)

兔C残篇:如何快速掌握 Java数组 (多维度剖析),第1张

兔C残篇:如何快速掌握 Java数组 (多维度剖析)

我在输入知识,也在用我理解后的方式进行输出

以下内容是 兔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.1关于兔C残篇

我们之前的残篇中提到过一个概念,就是java中的数据类型,分为两种,基本数据类型和引用数据类型,我们在兔C残篇方法的讲述中提到过,方法的返回值可以用基本数据类型,但是没有跟大家提到过引用数据类型,是因为我们兔C残篇还没有进展到面向对象的阶段,兔C残篇在现阶段,先进行java SE的相关知识输出。

1.2 关于什么是数组

回到话题,什么是数组,我们知道基本数据类型有,byte short int long float double char boolean。我们在使用这些数据类型声明变量的时候,都是一个变量一个变量进行声明的,可是如果我们的变量都是相同类型的声明呢?比如 我们需要声明10个int类型的变量,那这时候我们一个一个进行声明么?不! 我们可以用到数组,数组就可以帮我们存储10个相同类型的数据,不在需要变量来一个一个存储。

1.3 图解 变量和数组的区别

//变量 声明在栈中
//数组 声明在栈中,并通过存储的地址值指向了堆,在堆中开辟了空间

2. 数组的定义语法
// 数据类型[] 数组名称 = 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; i 
5.4 数组下标越界异常 

上面的for循环中,我们已经写上了注释声明,那如果取值范围超出数组的下标了呢?

比如现在我们存储了5个元素,那对应的下标是:0,1,2,3,4

如果我们偏偏取值 array[5]; 就会报出错误信息:java.lang.ArrayIndexOutOfBoundException 提示我们出现了数组下标越界异常,一般出现此错误,就是因为我们的取值时超出了存储的范围。

6. 数组的特点
  • 数组的长度是在创建时需要指定的,所以数组一旦被创建,就会在方法栈,方法堆中声明出对应的信息,比如声明在方法栈当中的对象名,存储用于指向方法堆当中具体实例化的空间内存地址值,比如方法堆中,会开辟出内存空间,空间中又会分割出小的空间来存储具体的值。
  • 声明出来的数组一定是用于存储一组相同数据类型的数据。
  • 数组可以存储基本数据类型,也可以是引用数据类型。只要是同一组相同的数据即可。
  • 数组属于引用类型,数组也可以看成是对象,数组中的每个元素,相当于该对象的成员变量。
  • 数组本身就是对象,java 的对象都是在堆中的,因此无论是用数组存储基本数据类型,还是引用数据类型,数组对象本身是在堆当中的。
  • 数组是有序类型的,它的顺序是按照我们存储的顺序排序的。
7. 数组练习题

//在这里我们先定义一个数组,然后在定义一个变量,然后以下的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):
     }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5695720.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存