1. 一维数组
1.1. 数组的概念
数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
变量: 在内存开辟一块空间。
数组: 也是变量,在内存中开辟一串连续的空间。数组长度一旦确定,就不能修改
数组的常见概念
- 数组名
- 下标(或索引)
- 元素
- 数组的长度
1.2. 基本用法
1. 格式
- 格式 1. 数据类型[] 数组名,属于只创建了数组引用名, 并未在内存创建数组空间
- 格式 2. 数据类型[] 数组名称 = new 数据类型[数组长度];
- 格式 3. 数据类型[] 数组名称 = {数组内容 1,数组内容 2,数组内容 3…数组内容 n};
- 格式 4. 数据类型[] 数组名称 = new 数据类型[]{内容 1,内容 2,内容 3…内容 n}
public static void main(String[]args){
// 1、声明数组
//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. 内存结构
在定义一个数组时,其数据内存分配如下图所示:
1.4. 一维数组实战
1. 读取数组
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. 数组的默认值
public static void main(String[] args) {
//int类型数组元素的默认值是0
int[] arr1=new int[4];
for(int i=0;i<arr1.length;i++) {
System.out.println(arr1[i]);
}
//double类型数组元素的默认值是0.0
double[] arr2=new double[4];
for(int i=0;i<arr2.length;i++) {
System.out.println(arr2[i]);
}
//String类型数组元素的默认值是null
String[] names=new String[5];
for(int i=0;i<names.length;i++) {
System.out.println(names[i]);
}
//char类型数组元素的默认值是' '
char[] genders=new char[5];
for(int i=0;i<genders.length;i++) {
System.out.println(genders[i]);
}
//boolean类型数组元素的默认值是false
System.out.println("over");
}
3. 求极值问题
public static void main(String[] args) {
//找出指定数组{12,43,-45,567,13}中的最大值和最小值
int[] arr= {12,43,-45,567,13};
//定义极值:一定数组元素,一般把第一个元素作为最大值的初始值
int max=arr[0];//12
int min=arr[0];
//循环比对
for(int i=1;i<arr.length;i++) {
if(arr[i]>max) {
max=arr[i];
}
if(arr[i]<min) {
min=arr[i];
}
}
System.out.println("最大值是:"+max);
System.out.println("最小值是:"+min);
}
2. 二维数组
对于二维数组的理解,我们可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。其实,从数组底层的运行机制来看,并没有多维数组,而是多个一维数组的嵌套组合。
2.1. 语法格式
格式1:
定义了名称为arr的二维数组
int[][] arr = new int[3][2]
- 二维数组中有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.2 二维数组的使用
public static void main(String[] args) {
//1、声明二维数组
//1.1 声明数组的同时开辟空间:数据类型[][] 数组名称=new 数据类型[行][列];
int[][] nns=new int[3][4];
//列的值:可以有:所有的行的列的个数相同,相当于矩形
// 可以省略,每一行都是null,需要自己去开辟空间--了解
//1.2 先声明数组再开辟空间
int[][] nns2;
nns=new int[3][4];
//1.3 声明数组的同时赋初值:行列的长度由赋值的个数决定了
int[][] nns3=new int[][] {{1,2},{3,4},{5,6}};
//1.4
int[][] nns4 = new int[3][];
nns4[0] = new int[] {1,2};
System.out.println(Arrays.toString(nns4));
System.out.println(Arrays.toString(nns4[0]));
//2、赋值
//使用循环赋值
for(int i=0;i<nns.length;i++) {
for(int j=0;j<nns[i].length;j++) {
nns[i][j]=i+j+4;
}
}
//3、取值
for(int i=0;i<nns3.length;i++) {
for(int j=0;j<nns3[i].length;j++) {
System.out.print(nns3[i][j]+" ");
}
System.out.println();
}
}
2.3. 二维数组的内存结构
2.4 二维数组练习
- 一维数组数组一重循环;2维数组数组2重循环;
- 一维数组一个下标索引;二维数组一定就是两个坐标(横纵坐标)
/*
* 数组中常见的异常: NullPointerException异常 空指针异常
* ArrayIndexOutOfBoundsException 数组下标越界
*/
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];
}
}
3.2. 数组的反转
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,j = arr.length - 1;i < j;i++,j--){
String temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
3.3. 线性查找数组
public static void main(String[] args) {
String[] arr = new String[]{"JJ","DD","MM","BB","GG","AA"};
//数组的复制(区别于数组变量的赋值:arr1 = arr)
String[] arr1 = new String[arr.length];
String dest = "BB";
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("很遗憾,没有找到的啦!");
}
}
3.3. 二分查找数组
public static void main(String[] args) {
int[] arr2 = new int[]{-98,-34,2,34,54,66,79,105,210,333};
int dest1 = -34;
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.4. 数组的排序(冒泡排序)
衡量排序算法的优劣:
- 时间复杂度:分析关键字的比较次数和记录的移动次数
- 空间复杂度:分析排序算法中需要多少辅助内存
- 稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算
法是稳定的。
public static void main(String[] args) {
int[] arr = new int[]{43,32,76,-98,0,64,33,-21,32,99};
//冒泡排序
for(int i = 0;i < arr.length - 1;i++){
for(int j = 0;j < arr.length - 1 - i;j++){
if(arr[j] > arr[j + 1]){
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for(int i = 0;i < arr.length;i++){
System.out.print(arr[i] + "\t");
}
}
4. Arrays工具类
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("未找到");
}
}