数组
数组的概念
数组(Array):是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通
过编号的方式对这些数据进行统一管理。
数组中的概念:
– 数组名
– 下标(或索引)
– 元素
– 数组的长度
数组的特点
• 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类
型和引用数据类型。
• 创建数组对象会在内存中开辟一整块连续的空间。占据的空间的大小,取决于数组的
长度和数组中元素的类型。
• 数组中的元素在内存中是依次紧密排列的,有序的。
• 数组,一旦初始化完成,其长度就是确定的。数组的长度一旦确定,就不能修改。
• 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
• 数组名中引用的是这块连续空间的首地址。
数组的初始化
//方法1:静态初始化
double[] prices1;
prices1 = new double[]{1,2,3,4,5,6,7,8};
//方法2:动态初始化
double[] prices2 = new double[]{1,2,3,4,5,6,7,8};
一维数组
一维数组的使用
数组的长度
数组的元素总个数,即数组的长度
每个数组都有一个属性 length 指明它的长度,例如:arr.length 指明数组 arr 的长度(即
元素个数)
每个数组都具有长度,而且一旦初始化,其长度就是确定,且是不可变的。
数组元素的引用
如何表示数组中的一个元素?
每一个存储到数组的元素,都会自动的拥有一个编号,从 0 开始,这个自动编号称为数组索引(index)或下标,可以通过数组的索引/下标访问到数组中的元素。
数组名[索引/下标]
数组的下标范围
Java 中数组的下标从[0]开始,下标范围是[0, 数组的长度-1],即[0, 数组名.length-1]
数组元素下标可以是整型常量或整型表达式。如 a[3] , b[i] , c[6*i];
一维数组的遍历
将数组中的每个元素分别获取出来,就是遍历。for 循环与数组的遍历是绝配。
class demo {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
//打印数组的属性,输出结果是 5
System.out.println("数组的长度:" + arr.length);
//遍历输出数组中的元素
System.out.println("数组的元素有:");
for(int i=0; i<arr.length; i++){
System.out.println(arr[i]);
}
}
}
数组元素的默认值
数组是引用类型,当我们使用动态初始化方式创建数组时,元素值只是默认
值。
class demo {
public static void main(String[] args) {
int a[]= new int[5];
System.out.println(a[3]); //a[3]的默认值为 0
}
}
对于基本数据类型而言,默认初始化值各有不同。
对于引用数据类型而言,默认初始化值为 null(注意与 0 不同!)
数组元素类型 | 元素默认初始值 |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0F |
double | 0.0 |
boolean | false |
char | 0或者为’\u0000’(表示为空) |
一维数组在内存中的存储
一个一维数组内存图
class demo {
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr);//[I@723279cf
}
}
两个一维数组内存图
class demo {
public static void main(String[] args) {
int[] arr = new int[3];
int[] arr2 = new int[2];
System.out.println(arr);
System.out.println(arr2);
}
}
两个变量指向一个一维数组
两个数组变量本质上代表同一个数组。因为地址是相同的
class demo {
public static void main(String[] args) {
// 定义数组,存储 3 个元素
int[] arr = new int[3];
//数组索引进行赋值
arr[0] = 5;
arr[1] = 6;
arr[2] = 7;
//输出 3 个索引上的元素值
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
//定义数组变量 arr2,将 arr 的地址赋值给 arr2
int[] arr2 = arr;
arr2[1] = 9;
System.out.println(arr[1]);
}
}
多维数组的使用
声明
二维数组声明的语法格式:
元素的数据类型[ ][ ] 二维数组的名称;
class demo {
public static void main(String[] args) {
int[][] grades;
}
}
静态初始化
格式:
int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}};
动态初始化
如果二维数组的每一个数据,甚至是每一行的列数,需要后期单独确定,那么
就只能使用动态初始化方式了。动态初始化方式分为两种格式:
格式 1:规则二维表:每一行的列数是相同的
(1)确定行数和列数
元素的数据类型[][] 二维数组名 = new 元素的数据类型[m][n];
//其中,m:表示这个二维数组有多少个一维数组。或者说一共二维表有几行
//其中,n:表示每一个一维数组的元素有多少个。或者说每一行共有一个单元格
//此时创建完数组,行数、列数确定,而且元素也都有默认值
(2)再为元素赋新值
二维数组名[行下标][列下标] = 值;
举例:
int[][] arr = new int[3][2];
- 定义了名称为 arr 的二维数组
- 二维数组中有 3 个一维数组
- 每一个一维数组中有 2 个元素
- 一维数组的名称分别为 arr[0], arr[1], arr[2]
- 给第一个一维数组 1 脚标位赋值为 78 写法是:arr[0][1] = 78;
格式 2:不规则:每一行的列数不一样
(1)先确定总行数
元素的数据类型[][] 二维数组名 = new 元素的数据类型[总行数][];
//此时只是确定了总行数,每一行里面现在是 null
(2)再确定每一行的列数,创建每一行的一维数组
二维数组名[行下标] = new 元素的数据类型[该行的总列数];
//此时已经 new 完的行的元素就有默认值了,没有 new 的行还是 null
//(3)再为元素赋值
二维数组名[行下标][列下标] = 值;
举例:
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]; //非法
数组的长度和角标
二维数组的长度/行数:二维数组名.length
二维数组的某一行:二维数组名[行下标],此时相当于获取其中一组数据。它本质上是一
个一维数组。行下标的范围:[0, 二维数组名.length-1]。此时把二维数组看成一维数组的
话,元素是行对象。
某一行的列数:二维数组名[行下标].length,因为二维数组的每一行是一个一维数组。
某一个元素:二维数组名[行下标][列下标],即先确定行/组,再确定列。
class demo {
public static void main(String[] args){
//存储 3 个小组的学员的成绩,分开存储,使用二维数组。
int[][] scores = {
{85,96,85,75},
{99,96,74,72,75},
{52,42,56,75}
};
System.out.println(scores);//[[I@15db9742
System.out.println("一共有" + scores.length +"组成绩.");
//[[:代表二维数组,I 代表元素类型是 int
System.out.println(scores[0]);//[I@6d06d69c
//[:代表一维数组,I 代表元素类型是 int
System.out.println(scores[1]);//[I@7852e922
System.out.println(scores[2]);//[I@4e25154f
//System.out.println(scores[3]);//ArrayIndexOutOfBoundsException: 3
System.out.println("第 1 组有" + scores[0].length +"个学员.");
System.out.println("第 2 组有" + scores[1].length +"个学员.");
System.out.println("第 3 组有" + scores[2].length +"个学员.");
System.out.println("第 1 组的每一个学员成绩如下:");
//第一行的元素
System.out.println(scores[0][0]);//85
System.out.println(scores[0][1]);//96
System.out.println(scores[0][2]);//85
System.out.println(scores[0][3]);//75
//System.out.println(scores[0][4]);//java.lang.ArrayIndexOutOfBoundsException: 4
}
}
二维数组的遍历
格式:
class demo {
public static void main(String[] args){
for(int i=0; i<二维数组名.length; i++){ //二维数组对象.length
for(int j=0; j<二维数组名[i].length; j++){//二维数组行对象.length
System.out.print(二维数组名[i][j]);
}
System.out.println();
}
}
}
内存解析
二维数组本质上是元素类型是一维数组的一维数组。
int[][] arr = {
{1},
{2,2},
{3,3,3},
{4,4,4,4},
{5,5,5,5,5}
};
扩容
实际上是换了一个数组
public class ExtendArr {
public static void main(String[] args) {
int[] arr = new int[]{9,0,1,6};
int[] newArr = new int[arr.length * 2];
for (int i = 0; i < arr.length; i++) {
newArr[i] = arr[i];
}
}
}
二分法查找
要求此数组必须是有序的。
public class Dichotomy {
public static void main(String[] args) {
int[] arr3 = new int[]{-99,-54,-2,0,2,33,43,256,999};
boolean isFlag = true;
int value = 256;
//int value = 25;
int head = 0;//首索引位置
int end = arr3.length - 1;//尾索引位置
while(head <= end){
int middle = (head + end) / 2;
if(arr3[middle] == value){
System.out.println("找到指定的元素,索引为:" + middle);
isFlag = false;
break;
}else if(arr3[middle] > value){
end = middle - 1;
}else{//arr3[middle] < value
head = middle + 1;
}
}
if(isFlag){
System.out.println("未找打指定的元素");
}
}
}