概述
文章目录
- 一、什么是数组
- 二、数组的声明与创建
- 三、初始化及内存分析
- 1、Java的内存
- 堆
- 栈
- 方法区
- 2、个人理解
- 3、三种初始化
- #静态初始化
- #动态初始化
- #默认初始化
- 四、数组的四大特点
- 五、数组边界
- ##小结
- 六、数组的使用
- 1、for..each循环
- 2、数组作方法入参
- 3、数组作返回值
- ##例题 写一个倒转数组的方法,输入和返回值都是数组;
- 七、二维数组/多维数组
- ##例题,写一个方法
- 八、补充知识
- 1、Arrays类
- 2、冒泡排序
- 练习:
- //思考 优化是如何实现的?
- 3、稀疏数组
- #自己布置个作业:设计两个方法,可以实现普通数组和稀疏数组的转化
一、什么是数组
数组是相同数据类型的有序集合
二、数组的声明与创建
1、首先必须声明数组变量,才能在程序中使用数组。
-
语法:
dataType[] arrayRefVar; //首先的方法 或 dataType arrayRefVar[];
//举例 int[] nums; 或 int nums[]; //后者是C的格式
2、Java语言使用操作符new 来创建数组,语法如下
-
语法
dataType[] arrayRefVar = new dataType[arraySize]; //arraySize表示数组的长度(元素的数量)
3、数组的元素是通过索引访问的,数组索引从0开始
4、数组长度获取:array.length
举例:
public class Demo {
public static void main(String[] args) {
int[] nums; //1 声明一个数组
//== int nums[];
nums =new int[10]; //2 给数组划分(10个)空间
//== 1和2可以合起来声明 即 int[] nums = new int[10];
nums[0]=1;//3 给数组中的元素赋值
nums[1]=2;
nums[2]=3;
nums[3]=4;
nums[4]=5;
nums[5]=6;
nums[6]=7;
nums[7]=8;
nums[8]=9;
nums[9]=10;
int sum=0;
//求和
for (int i = 0; i < nums.length; i++) {
//nums.length数组的长度
sum+=nums[i];
}
System.out.println(sum);
}
}
三、初始化及内存分析
java 的内存:堆、栈、方法区等等
1、Java的内存
堆
- 存放new(新建的)的对象和数组
- 可以被所有的线程共享,不会存放别的对象引用
栈
- 存放基本变量类型(会包含这个基本类型的具体数值)
- 引用对象的变量(会存放这个引用在堆里的具体地址)
方法区
- 可以被所有线程共享
- 也包含了所有的class和static变量
2、个人理解
- 堆和栈,方法区的具体概念目前没教,可以再深入了解
- 个人简单理解:
- 当我们“声明一个数组”时,这个数组的内存在栈里;
- 当我们“创建一个数组”时,会对应的在堆里占用固定数量的内存;
- 当我们“给数组元素赋值时”,会在堆里给对应的元素赋值;
- 常见的错误
ArrayIndexOutOfBoundsException
:数组下边超出边界的异常- 当我们引用的数组元素对应的下标超过了数组的总数时,报错。
- 也就是说数组的元素数量在创建数组时就已经确定。
- “声明”和“创建”数组可以同时进行,语句可以写成一行。
3、三种初始化
#静态初始化
-
格式:
int[] a= {1,2,3,4,5,6,7,8}
-
一旦定义,长度就固定了,无法改变
-
但是数组的元素是可以再次改变的。测试如下:
public class Demo { public static void main(String[] args){ int[] a= {1,2,3,4,5,6}; a[3] = 100;//改变第四个元素的值 for (int i = 0; i < a.length; i++) { System.out.println(a[i]); } } } // 结论 :显然是可以再改变的
-
相当于:声明+创建+赋值 一起进行
#动态初始化
- 就是前面提到的方法,先声明和创建数组,后续再对元素进行赋值
- 与静态不同的是,赋值的步骤是分开的。
- 并且当没有赋值时,相当于“默认初始化”
#默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
- 如基本数字类型的初始值是0或0.0 ,boolean值的初始值是false,其他类型的初始值是 null
四、数组的四大特点
1、数组的长度是确定的,一旦被创建,就不可改变
2、数组的元素必须是相同类型的,不允许出现混合类型。
- 注意,经过测试,这个类型符合之前血的“基本类型的优先级”一说,也就是可以在高级的数组中定义低级的元素,因为会自动转换类型
3、数组中的元素,可以是基本类型和引用类型
4、数组变量本身属于引用类型,数组也可以看成是对象,每个元素相当于该对象的成员对象;
-
数组本身就是对象,Java中对象是在堆中
-
因此,数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的
先记住概念
五、数组边界
- 下标 的合法区间:[0,length-1 ],如果越界就会报错:
ArrayIndexOutOfBoundsException
数组下标越界异常
##小结
- 数组是相同数据类型的有序集合
- 数组也是对象。数组元素相当于对象的成员变量。
- 数组的长度是确定,不可变的。下标不可越界。
六、数组的使用
1、for…each循环
-
优点:书写简单,JDK1.5的新特质,通过for循环遍历数组
-
缺点:没有下标
public class DemoArray { public static void main(String[] args){ int[] d= {1,2,3,4,5}; for(int D : d){ //for..each循环 // 语法:for(数据类型 元素 :数组) System.out.println(D); } } }
2、数组作方法入参
3、数组作返回值
##例题 写一个倒转数组的方法,输入和返回值都是数组;
public class DemoArray {
public static void main(String[] args){
int[] d= {1,2,3,4,5};
int[] r = reverse(d);//调用反转数组的方法
for(int rr: r){ //使用for..each循环遍历数组
System.out.println(rr);
}
}
public static int[] reverse(int[] Base ){
int[] reslut = new int[Base.length]; //创建一个新数组作为返回值
int a=0;
for (int i = 0; i < Base.length ; i++) {
reslut[Base.length-1-i] = Base[i];
//将新数组的最后一个元素赋值为旧数组的第一个元素
//……以此类推
//注意:下标超出边界异常
}
return reslut;
}
运行成功
七、二维数组/多维数组
是数组之间进行嵌套
-
多维数组可以看成是数组的数组;
-
比如二维数组就是一个特殊的的数组,其每个元素都是一个一维数组
-
语法(二维
-
int[][] a = new int[2][5];
-
==
int a[][] = new int[2][5];
//前面的行,后面是列 -
以上,二维数组a可以看成一个二行五列的数组。
-
//实际使用中,Java最多使用二维数组,很少用到多维数组
##例题,写一个方法
- 可以提取二维数组的元素,并且实现换行
public class DemoArray02 {
static public void printArray(int[][] a){
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
System.out.printf(a[i][j]+" ");
if( j == a[i].length-1 ){
System.out.println(); //当j是本行最后一个元素时,换行
}
}
}
}
public static void main(String[] args) {
int[][] array = {{2,3},{4,5},{1,5},{22,1}};
printArray(array); //调用printArray方法
}
}
运行成功
八、补充知识
1、Arrays类
-
数组的工具类 java.until.Arrays
-
可以阅读JDK帮助文档了解详细
-
常用的函数
Arrays.toString()
:打印出(一维)数组元素Arrays.deepToString
:打印多维数组元素Arrays.sort
:数组排序,升序。返回值为空。Arrays.fill(数组,数值)
:对(一维)数组的每个元素赋值Arrays.binarySearch(数组,key)
:在(一维)数组中查找某个元素的值跟key 是否相等,并且返回下标- …………
-
Arrays类的方法都是使用static修饰的静态方法,可以直接用类名进行调用。
2、冒泡排序
总共有八大排序,冒泡排序是最出名的,也是面试经常要考的
- 视频演示
- 两层循环,外层确定冒泡论述,里层依次比较。
- 算法的时间复杂度为O(n2)
练习:
- //写一个方法实现一维数组的冒泡排序
public class Demo01 {
public static int[] sort(int[] array){
int a = 0;
// 外层循环确定冒泡排序的循环次数
for (int i = 0; i < array.length-1; i++) {
//优化: 可以引入flag,用于判断数组是否已排序完毕,如是,则结束循环
boolean flag =false;
//内存比较每个元素并交换位置
for (int j = 0; j < array.length-1-i; j++) {
if( array[j] > array[j+1] ){
//!两数交换,注意不要写反了
a = array[j];
array[j] = array[j+1];
array[j+1] = a;
flag = true;
}
}
if(flag==false){
break;
}
//思考 优化是如何实现的?
// 引入flag,之前我们有思考过引入flag是代表什么意思?——“一旦”
// 也就说 在进行内层循时,一旦进行了两数比较(if分支成立),flag就会发生变化;
// 反之,如果都没有进行if分支,则flag不会变。
// 我们最终检测flag有没有变化,则可以得知内层循环有没有成功运行,即数组是否已经排序完毕
// 目标就是减少在数组已经排序完毕后,再进行多余的内层循环,从而达到优化的目的
}
return array;
}
public static void main(String[] args){
int[] a = {8,2,4,3,7,1};
System.out.println(Arrays.toString(a));
int[] b = sort(a);
System.out.println(Arrays.toString(b));
}
}
//思考 优化是如何实现的?
-
引入flag,之前我们有思考过,引入flag的相当于语义中的什么意思?——“一旦”
- 也就说 在进行内层循时,一旦进行了两数比较(if分支成立),flag就会发生变化;
- 反之,如果都没有进行if分支,则flag不会变。
- 并且需要注意的是,在进行逻辑分析时要避免一个误区**“符合条件flag变化,不符合条件flag会恢复”**
- 实际情况是:flag一旦发生变化,flag是不会在本次循环中恢复了
-
我们最终检测flag有没有变化,则可以得知内层循环有没有成功运行,
- 即检测 数组是否已经排序完毕。
-
优化的目标就是:减少在数组已经排序完毕后,再进行多余的内层循环,从而达到节约掉后续运算占用资源的效果。
3、稀疏数组
是一种数据结构。。
比如有个需求:编写五子棋游戏
- 分析问题:因为该二维数组的很多值都是默认值,因此记录了很多没有意义的数据。
- 解决方法——稀疏数组
-
当一个数组中大多数元素为0(或同一数值)时,可以用稀疏数组来保存该数组。
-
处理方式:
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素 :行列和值记录在一个小规模的数组中,从而缩小程序的规模——>压缩数据存储空间
-
视频讲解:地址
#自己布置个作业:设计两个方法,可以实现普通数组和稀疏数组的转化
学习时间 2022年4月15日
public class Demo02 {
//先定义一个方法 二维数组转换成稀疏数组
public static int[][] transform01(int[][] arrayIn){
int arrayLength = 0;
// 1、求出稀疏数组的行数arrayLength,即求二维数组里有几个非0是数字
for (int i = 0; i < arrayIn.length; i++) {
for (int j = 0; j < arrayIn[i].length; j++) {
if(arrayIn[i][j] != 0){
arrayLength++;
}
}
}
// 2、初始化稀疏数组;
int[][] arrayOut=new int[arrayLength+1][3];
// 3、求第一行的元素,即求[行,列,非0的数数量]
arrayOut[0][0] = arrayIn.length;
arrayOut[0][1] = arrayIn[0].length;
arrayOut[0][2] = arrayLength;
// 4、求接下来的数组
//for (int k = 1; k < arrayLength ; k++) {
// 再次遍历二维数组,寻找非0元素,进行赋值
int k = 1; //定义k指稀疏数组的行数
for (int i = 0; i < arrayIn.length; i++) {
for (int j = 0; j < arrayIn[i].length; j++) {
if (arrayIn[i][j] != 0) {
arrayOut[k][0] = i;
arrayOut[k][1] = j;
arrayOut[k][2] = arrayIn[i][j];
// 找到一个非0 元素 ,行数k++
k++;
}
}
}
return arrayOut;
}
//设计方法二:把稀疏数组转化为二维数组
public static int[][] transform02(int[][] arrayIn){
//进阶:设置异常检测;
if (arrayIn[0][2] >= arrayIn.length-1){
System.out.println("稀疏数组有误");
int[][] a = {{0},{0}};
return a;
}
// 1、定义并初始化二维数组
int[][] arrayOut = new int[ arrayIn[0][0] ][ arrayIn[0][1] ];
// 2、遍历第二行及之后的每行元素,即可求出二维数组中的非0元素数值和位置
for (int i = 1; i < arrayIn.length; i++) {
arrayOut[ arrayIn[i][0] ][ arrayIn[i][1] ] = arrayIn[i][2];
}
return arrayOut;
}
//测试:
public static void main(String[] args) {
int[][] a = {{0,0,1,0,0},{0,1,0,0,0},{0,0,0,1,1}};
int[][] b= transform01(a);
System.out.println("测试一:");
System.out.println("二维数组为"+Arrays.deepToString(a));
System.out.println("使用方法tansform01转化为稀疏数组:"+Arrays.deepToString(b));
int[][] c = transform02(b);
System.out.println("测试二:");
System.out.println("稀疏数组为"+Arrays.deepToString(b));
System.out.println("使用方法tansform01转化为二维数组:"+Arrays.deepToString(c));
System.out.println("再测一个复杂的================");
int[][] a1 = {{0,0,87,666,64},{0,86,0,0,1},{0,0,0,1,0},{12,0,99,0,0}};
int[][] b1= transform01(a1);
System.out.println("测试一:");
System.out.println("二维数组为"+Arrays.deepToString(a1));
System.out.println("使用方法tansform01转化为稀疏数组:"+Arrays.deepToString(b1));
int[][] c1 = transform02(b1);
System.out.println("测试二:");
System.out.println("稀疏数组为"+Arrays.deepToString(b1));
System.out.println("使用方法tansform01转化为二维数组:"+Arrays.deepToString(c1));
System.out.println("再测一个异常的================");
int[][] b2 = {{4,2,3},{0,1,5},{1,0,5},{2,1,2},{3,0,1}};
int[][] c2 = transform02(b2);
}
}
//结果
测试一:
二维数组为[[0, 0, 1, 0, 0], [0, 1, 0, 0, 0], [0, 0, 0, 1, 1]]
使用方法tansform01转化为稀疏数组:[[3, 5, 4], [0, 2, 1], [1, 1, 1], [2, 3, 1], [2, 4, 1]]
测试二:
稀疏数组为[[3, 5, 4], [0, 2, 1], [1, 1, 1], [2, 3, 1], [2, 4, 1]]
使用方法tansform01转化为二维数组:[[0, 0, 1, 0, 0], [0, 1, 0, 0, 0], [0, 0, 0, 1, 1]]
再测一个复杂的================
测试一:
二维数组为[[0, 0, 87, 666, 64], [0, 86, 0, 0, 1], [0, 0, 0, 1, 0], [12, 0, 99, 0, 0]]
使用方法tansform01转化为稀疏数组:[[4, 5, 8], [0, 2, 87], [0, 3, 666], [0, 4, 64], [1, 1, 86], [1, 4, 1], [2, 3, 1], [3, 0, 12], [3, 2, 99]]
测试二:
稀疏数组为[[4, 5, 8], [0, 2, 87], [0, 3, 666], [0, 4, 64], [1, 1, 86], [1, 4, 1], [2, 3, 1], [3, 0, 12], [3, 2, 99]]
使用方法tansform01转化为二维数组:[[0, 0, 87, 666, 64], [0, 86, 0, 0, 1], [0, 0, 0, 1, 0], [12, 0, 99, 0, 0]]
再测一个异常的================
稀疏数组有误
最后
以上就是阳光草莓为你收集整理的Java05.数组篇一、什么是数组二、数组的声明与创建三、初始化及内存分析四、数组的四大特点五、数组边界##小结六、数组的使用七、二维数组/多维数组八、补充知识的全部内容,希望文章能够帮你解决Java05.数组篇一、什么是数组二、数组的声明与创建三、初始化及内存分析四、数组的四大特点五、数组边界##小结六、数组的使用七、二维数组/多维数组八、补充知识所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复