JAVA数组
1一维数组
1.1 概念
数组(Array)是有序的元素序列。若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。这些有序排列的同类数据元素的集合称为数组。数组会在内存中开辟一连串的空间,数组长度一旦确定,就不能更改。
数组一般由数组名、下标(或索引)、元素、数组长度组成。
1.2 基本用法
- 格式
格式 1. 数据类型[] 数组名,属于只创建了数组引用名, 并未在内存创建数组空间
格式 2. 数据类型[] 数组名称 = new 数据类型[数组长度];
格式 3. 数据类型[] 数组名称 = {数组内容 1,数组内容 2,数组内容 3…数组内容 n};
格式 4. 数据类型[] 数组名称 = new 数据类型[]{内容 1,内容 2,内容 3…内容 n}
2 代码
public static void main(String[] args) {
// 1、声明数组
1
2
1.3 内存结构
JMM
JVM的内存结构
第四行代码内存状态
第5行代码内存状态
//1.1 先声明,后开辟空间:数据类型[] 数组名称;
int[] arr1;//声明
arr1=new int[4];//开辟空间:数组名称=new 数据类型[数组长度]; 数组的长度一旦
确定,不可以改变
//1.2 声明数组的同时开辟空间
double[] arr2=new double[5];
System.out.println(arr1);
System.out.println(arr2);
//1.3 声明数组
String[] arr3;//只是声明,没有在内存中开辟数组空间
//System.out.println(arr3);
//1.4 声明数组的同时赋值 数据类型[] 数组名称=new 数据类型[]{数组值1,数组值2,
数组值3,数组值4......数组值n};
//此时数组的长度由赋值的个数决定
int[] arr4=new int[]{1,2,3,4,5};
System.out.println(arr4);
//1.5 声明数组的同时赋值 数据类型[] 数组名称={数组值1,数组值2,数组值3,数组值
4......数组值n};
//此时数组的长度由赋值的个数决定
double[] arr5= {1.5,3.6,5.8,4.0};
}
1.3 内存结构
JMM内存结构
写一段简单的代码
int[] array = new int[4];
System.out.println(array);
执行完这段代码,结果如下:
可见,array仅仅存了一个内存地址。
当我们给数组中元素赋值后,用循环输出数组,见下图。可见,数组中也是可以赋值的,那数组内存结构到底是什么样的呢?见下图。
当创建一个数组时,先在栈中存储一个地址,这个地址指向堆中的内存。
1.4 案例
- 读取数组
取出数组中的值:数组名称[下标索引]
public static void main(String[] args) {
//1、声明数组并开辟空间
int[] arr1=new int[4];
//2、给数组赋值:数组名称[下标索引]=值;下标索引从0开始,最大比数组长度小1
//数组长度:数组名称.length获取
//原始赋值方式:
/*
* arr1[0]=2;
* arr1[1]=4;
* arr1[2]=6;
* arr1[3]=8;
*/
//推荐使用循环的方式数组
for(int i=0;i<arr1.length;i++) {
arr1[i]=i+1;
}
//3、使用数组
for(int i=0;i<arr1.length;i++) {
System.out.println(arr1[i]);
}
}
2 二维数组
2.1 概念
对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存
在。其实,从数组底层的运行机制来看,其实没有多维数组
2.2 基本用法
1 格式语法
格式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;
2.3 内存结构
和一维数组内存结构类似,二维数组的内存结构如下图
int[][] arr1 = new int[3][2];
arr1[0][1] = 3;
2.4 案例
基本都跟循环打交道;一维数组数组一重循环;2维数组数组2重循环;
基本离不开坐标问题;一维数组一个下标索引;二维数组一定就是两个坐标(横纵坐标)
public class Demo23 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//1、计算3个班级所有学生的平均分:每个班级有n个人,要求先输出各个班级的自己的平均
分
double[][] score=new double[3][];//列数省略,需要自己去开辟空间
for(int i=0;i<score.length;i++) {
double sum=0;
System.out.print("请输入第"+(i+1)+"个班级的学生人数:");
int num=input.nextInt();
score[i]=new double[num];//不开空间默认null,会报出
NullPointerException异常
//System.out.println(score[i]);
for(int j=0;j<num;j++) {
System.out.print("请输入第"+(j+1)+"个同学的成绩:");
score[i][j]=input.nextDouble();
sum+=score[i][j];
}
System.out.println("第个班级的平均分是:"+sum/num);
}
}
}
3 数组中常见算法
3.1 二分查找
数组的复制、反转、查找(线性查找、二分法查找)
public static void main(String[] args) {
String[] arr = new String[]{"JJ","DD","MM","BB","GG","AA"};
//数组的复制(区别于数组变量的赋值:arr1 = arr)
String[] arr1 = new String[arr.length];
for(int i = 0;i < arr1.length;i++){
arr1[i] = arr[i];
}
//数组的反转
// for(int i = 0,j = arr.length - 1;i < j;i++,j--){
// String temp = arr[i];
// arr[i] = arr[j];
// arr[j] = temp;
// }
//遍历
for(int i = 0;i < arr.length;i++){
System.out.print(arr[i] + "\t");
}
System.out.println();
//查找(或搜索)
//线性查找:
String dest = "BB";
dest = "CC";
boolean isFlag = true;
for(int i = 0;i < arr.length;i++){
if(dest.equals(arr[i])){
System.out.println("找到了指定的元素,位置为:" + i);
isFlag = false;
break;
}
}
if(isFlag){
System.out.println("很遗憾,没有找到的啦!");
}
//二分法查找:(熟悉)
//前提:所要查找的数组必须有序。
int[] arr2 = new int[]{-98,-34,2,34,54,66,79,105,210,333};
int dest1 = -34;
dest1 = 35;
int head = 0;//初始的首索引
int end = arr2.length - 1;//初始的末索引
boolean isFlag1 = true;
while(head <= end){
int middle = (head + end)/2;
if(dest1 == arr2[middle]){
System.out.println("找到了指定的元素,位置为:" + middle);
isFlag1 = false;
break;
}else if(arr2[middle] > dest1){
end = middle - 1;
}else{//arr2[middle] < dest1
head = middle + 1;
}
}
if(isFlag1){
System.out.println("很遗憾,没有找到的啦!");
}
}
二分查找的过程如下
3.2 排序算法
衡量排序算法的优劣:
时间复杂度:分析关键字的比较次数和记录的移动次数
空间复杂度:分析排序算法中需要多少辅助内存
稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算
法是稳定的。
3.3 冒泡算法
public static void main(String[] args) {
//1.boolean equals(int[] a,int[] b):判断两个数组是否相等。
int[] arr1 = new int[]{1,2,3,4};
int[] arr2 = new int[]{1,2,3,4};
boolean isEquals = Arrays.equals(arr1, arr2);
System.out.println(isEquals);
//2.String toString(int[] a):输出数组信息。
System.out.println(Arrays.toString(arr1));
//3.void fill(int[] a,int val):将指定值填充到数组之中。
Arrays.fill(arr1,10);
System.out.println(Arrays.toString(arr1));
//4.void sort(int[] a):对数组进行排序。
Arrays.sort(arr2);
System.out.println(Arrays.toString(arr2));
//5.int binarySearch(int[] a,int key)
int[] arr3 = new int[]{-98,-34,2,34,54,66,79,105,210,333};
int index = Arrays.binarySearch(arr3, 210);
if(index >= 0){
System.out.println(index);
}else{
System.out.println("未找到");
}
}