一、什么是数组
- 数组是存储同一种数据类型多个元素的集合。也可以看成是一个容器。
- 数组既可以存储基本数据类型,也可以存储引用数据类型。
- 数组一旦初始化,长度不可变。
二、一维数组
- 一维数组的声明方式:类型 数组名[] 或 类型[] 数组名,例如:
int a[];
int[] a1;
double b[];
Date[] c; //对象数组
- 单独声明数组时不能指定其长度(数组中元素的数),例如:
int a[5]; //非法
- 这两种定义做完了,数组中是没有元素值的
1、数组的初始化
- Java中的数组必须先初始化,然后才能使用
- 所谓初始化:就是为数组中的数组元素分配内存空间,并为每个数组元素赋值
- Java中可以使用关键字new创建数组对象,完成静态初始化或动态初始化
1.1、动态初始化
- 动态初始化:初始化时只指定数组长度,由系统为数组分配初始值
- 格式:数据类型[] 数组名 = new 数据类型[数组长度],如 int[] arr = new int[3];
- 数组长度其实就是数组中元素的个数
1.1.1、数组中的元素
- 定义并用运算符new为之分配空间后,才可以引用数组中的某个元素;
- 每个数组都有一个属性length 指明它的长度,例如:a.length指明数组a 的长度(元素个数);
- 数组名和编号的配合就可以获取数组中的指定编号的元素。即索引(下标);
- 数组元素的引用方式:数组名[数组元素下标]
- 数组元素下标可以是整型常量或整型表达式。如a[3] , b[i] , c[6*i]
- 数组元素下标从0开始;长度为n的数组合法下标取值范围: 0 至n-1
1.1.2、内存结构
- 动态初始化数组时,由系统给出初始值,初始值为0
- Java中内存的申请和释放都是 JVM进行管理的,Java程序要运行,JVM都会自动的向电脑申请一块内存,把这块内存分为五部分:
- 栈(Stack):主要存放局部变量,即在方法定义中或方法声明上的变量
- 堆(Heap):凡是new出来的都存在堆里面,堆当中的数据都有默认原则
整数:0,小数:0.0,布尔:false,char:空格,引用数据类型:null - 方法区(Method Area):存放的是与.class相关的信息
- 本地方法区(Native Method Area):与操作系统有关
- 寄存器(Register):与CPU有关
堆内存的特点:
- 每一个new出来的东西都会有一个地址;
- 每个变量都会有默认值;
- 使用完毕就变成了垃圾,但是并没有立即回收,会等到垃圾回收器空闲时回收。
栈内存的特点:
- 用完就释放掉
1.2、静态初始化
- 静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度
- 格式:数据类型[] 数组名= new 数据类型[]{元素1,元素2,…}
- 举例:int[] arr = new int[]{1,2,3} 或 int[] arr= {1,2,3}
注意:
int[] a = new int[]:
- new的时候就要分配内存,不指定就不知道分配多少;
- 数组一旦初始化,长度不可变。
1.3、数组常见问题
1.3.1、数组索引越界
- ArrayIndexOutOfBoundsException
- 访问到了数组中的不存在的索引时发生
1.3.2、空指针异常
- NullPointerException
- 数组引用没有指向实体,却在操作实体中的元素时
2、数组排序
2.1、冒泡排序
冒泡排序的基本思路:
假设要被排序的数组arr[0…n-1]是垂直放置的,我们将其中的每个元素都看成重量为arr[i]的气泡。那么,根据常识,我们知道重量轻的气泡会向上冒。所以我们制定轻气泡不能在重气泡下的原则。现在,我们从下向上扫描数组arr[n]中的每个元素,凡是发现违反本原则的轻气泡,就使其向上“冒”,反复的执行这个过程,直到所有元素都满足该原则。
2.1.1、冒泡算法原理
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
2.1.2、冒泡排序效果
分析:每次比较相邻两数小的交换到前面每轮结束后最大的数交换到最后
2.1.3、代码框架:
for (i = 0; i < N-1 ; i++){ //外层控制趟数
for (j = 0; j < N-1-i; j++){ //内层控制次数
// 比较j 和j+1 位置的元素
// 如果前大后小就交换
}
}
/**
*冒泡排序速记口诀(升序):
* N 个数字来排队
* 两两相比小靠前
* 外层循环N-1
* 内层循环N-1-i
*/
2.1.4、冒泡排序示例:
/*
*使用冒泡算法对数组排序
*int[] number =new int[]{20,5,17,28,19,15,29,87,65,32}
*要求:从大到小进行打印
**/
public void test5() {
int temp;
int[] number = new int[]{20,5,17,28,19,15,29,87,65,32};
for (int i = 0; i < number.length - 1; i++) {
for (int j = 0; j < number.length - 1 - i; j++) {
if (number[j] < number[j + 1]) {
temp = number[j];
number[j] = number[j + 1];
number[j + 1] = temp;
}
}
}
/*for (int n : number) {
System.out.print(" "+n);
}*/
System.out.println(Arrays.toString(number));
}
2.2、选择排序(了解)
算法描述:
对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换;接着对不包括第一个记录以外的其他记录进行第二轮比较,得到最小的记录并与第二个记录进行位置交换;重复该过程,直到进行比较的记录只有一个时为止。
三、多维数组
二维数组[][]:数组中的数组
格式1(动态初始化):int[][] arr= new int[3][2];
- 定义了名称为arr的二维数组
- 二维数组中有3个一维数组
- 每一个一维数组中有2个元素
- 一维数组的名称分别为arr[0], arr[1], arr[2]
- 给第一个一维数组1脚标位赋值为78写法是:arr[0][1] = 78;
格式2(动态初始化):int[][] arr= new int[3][];
- 二维数组中有3个一维数组
- 每个一维数组都是默认初始化值null (注意:区别于格式1)
- 可以对这三个一维数组分别进行初始化
arr[0] = new int[3]; arr[1] = new int[1]; arr[2] = new int[2]; - 注:int[][] arr= new int[][3]; //非法,第一个值不能为空
格式3(静态初始化):int[][] arr= new int[][]{{3,8,2},{2,7},{9,0,1,6}};
- 定义一个名称为arr的二维数组,二维数组中有三个一维数组
- 每一个一维数组中具体元素也都已初始化
- 第一个一维数组arr[0] = {3,8,2};
- 第二个一维数组arr[1] = {2,7};
- 第三个一维数组arr[2] = {9,0,1,6};
- 第三个一维数组的长度表示方式:arr[2].length;
➢注意特殊写法情况:int[] x,y[]; x是一维数组,y是二维数组。
➢Java中多维数组不必都是规则矩阵形式
二维数组示例:
public void test6() {
int[][] house = new int[][]{{101,102,103,104},{201,202,203,204},{301,302,303,304}};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
System.out.print(house[i][j]+" ");
}
System.out.println();
}
}