04-数组
✨你好啊,我是“ 罗师傅”,是一名程序猿哦。
🌍主页链接:楚门的世界 - 一个热爱学习和运动的程序猿
☀️博文主更方向为:分享自己的快乐 briup-jp3-ing
❤️一个“不想让我曾没有做好的也成为你的遗憾”的博主。
💪很高兴与你相遇,一起加油!
前言
目标:Java基础编程,熟练Java开发语法和规则,养成良好编程习惯
数组概述
数组,表示一块连续的内存空间,可用来存储多个数据(元素),要求元素类型要一致。
数组定义
数据类型[] 数组名(推荐)
1 int[] arr1;数据类型 数组名[]
1 int arr1[];
数组内存理解
attention:
- 数组是引用数据类型,用来存储一个引用值(可理解为地址值)
- 数组/变量 没有进行初始化,不可直接使用
数组初始化
定义数组(开辟栈空间内存)的同时,给其赋上初值,就叫做数组的初始化!
动态初始化
格式:
数据类型[] 数组名 = new 数据类型[数组长度]
案例:
1 int[] arr1 = new int[3];注意:
- new是一个关键字,表示数组在堆内存区域开辟内存空间
- 等号两边的数据类型要一致(继承、实现不一定)
- 数组长度必须要有,可以>=0(一般大于0),但不能为负数
内存构成
数组名标识的那块内存(栈空间),存放了一个引用值(地址值),通过该地址值可以找到堆空间相应内存(用来存放数组中所有元素)
堆空间内存存在默认初始化:整数型=0,浮点数=0.0,引用类型=null,字符类型=\u0000
1
2
3
4
5
6 /* 输出结果为:[I@15db9742
* [ : 当前的空间是一个数组类型
* I : 当前数组容器中所存储的数据类型
* @ : 分隔符
* 15db9742 : 堆空间十六进制内存地址
*/
数组下标
数组的下标的区间为[0, 数组长度-1]
minIndex = 0, maxIndex = length - 1
通过下标可以访问数组中元素
1 int a = arr[1];通过数组下标给数组元素赋值
1 arr[1] = 100;结合循环来赋值或者取值
1
2
3
4
5
6
7
8
9
10 int[] arr = new int[4];
for(int i = 0; i < 4; i++) { // 循环赋值
arr[i] = i + 1;
}
for(int i = 0; i < 4; i++) { // 循环取值
System.out.println(arr[i]);
}
for(int i: arr) { // foreach主要用来遍历,赋值不会对原来的数据产生影响
System.out.println(arr[i]);
}
数组长度
数组长度:是指在一个数组中,可以存放同一类型元素的最大数量。
获取数组长度固定格式:
数组名.length
1
2 intp[] arr = new int[4];
System.out.println(arr.length);数组长度注意事项:
- 数组长度,必须在创建数组对象的时候就明确指定
- 数组长度,一旦确定,就无法再改变
- 数组长度,可以>=0 (一般大于0),但不能为负数
数组默认值
数组在创建时,会开辟2块内存,数组名对应栈空间那块内存,数组元素会 存放在堆空间。
堆空间数组每一个元素位置上,存在相应的默认值,要么为0,要么为0.0, 要么为null。
1
2
3
4
5
6
7
8
9
10 // byte、short、int、long类型数组中的默认值为0
int[] a = new int[4]; // 默认4个数据全是0
// float、double类型数组中的默认值为 0.0
double[] d = new double[4]; // 默认4个数据全是0.0
// boolean类型数组中的默认值为false
boolean[] d = new boolean[4]; // 默认4个数据全是false
// char类型数组中的默认值为 '\u0000'
char[] d = new char[4]; // 默认4个数据全是 '\u0000'
// 引用类型数组中的默认值为null
String[] d = new String[4]; // 默认4个数据全是null
静态初始化
在创建数组的同时,直接初始化数组元素的值,就称为数组的静态初始。
静态初始化格式:
完整版格式:
1
2 // 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,...};
int[] arr = new int[]{1,2,3,4,5};简化版格式:
1
2 // 数据类型[] 数组名 = {元素1,元素2,...};
int[] arr = {1,2,3,4,5};注意:数组静态初始化书写方式要严格按照上述两种方式!
错误展示:
1
2
3
4
5 //错误方式1:不能明确数组长度
int[] arr4 = new int[3]{1,2,3};
//错误方式2:简化版格式必须严格按照上述格式书写,不能分两行书写
int[] arr5;
arr5 = {1,2,3};
内存补充
- 两个数组内存结构图
- 使用数组赋值
数组异常
索引越界异常
1
2 int[] arr = new int[4];
System.out.println(arr[4]); // java.lang.ArrayIndexOutOfBoundsException: 4
空指针异常
1
2
3 int[] arr = new int[4];
arr = null;
System.out.println(arr[0]); // java.lang.NullPointerExceptionarr = null 这行代码,意味着变量arr将不会在保存数组的内存地址,我 们通过arr这个标识符再也找不到堆空间数组元素,因此运行的时候会抛出 NullPointerException 空指针异常。
工具类
java.util.Arrays 类,是JavaSE API中提供给我们使用的一个工具类,这个类 中包含了操作数组的常用方法,比如排序、查询、复制、填充数据等,借助它我 们在代码中操作数组会更方便。
Arrays中的常用方法:
- toString方法
- 可以把一个数组变为对应的String形式
- copyOf方法
- 可以把一个数组进行复制 该方法中也是采用了arraycopy方法来实现的功能
- sort方法
- 可以对数组进行排序
- binarySearch方法
- 在数组中,查找指定的值,返回这个指定的值在数组中的下标,但是查找之 前需要在数组中先进行排序,可以使用sort方法先进行排序
- copyOfRange方法(了解)
- 也是复制数组的方法,但是可以指定从哪一个下标位置开始复制 该方法中也是采用了arraycopy方法来实现的功能
- fill(了解)
- 可以使用一个特定的值,把数组中的空间全都赋成这个值
扩展案例
选择排序
插入排序
希尔排序
看我的这篇博客即可:基础篇-interview-heima
数组拷贝
数组的长度确定后便不能修改,如果需要数组存放更多元素,可以通过创建长度更长的新数组,然后先复制老数组内容到新数组中,再往新数组中放入额外的元素。
1
2
3
4
5
6
7
8
9 // java.lang.System arraycopy() 复制数组功能
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
// src: 需要 被 复制的目标数组
// srcPos: 从目标数组的哪一个位置开始复制
// dest: 需要把数据复制到另外一个新的数组中
// destPos: 把数据复制到新数组的时候,需要把数据从什么位置开始复制进去
// length: 复制的目标数组的长度案例:定义一个方法,传递一个数组对象给它,其将数组长度扩大到原来的2倍返回。
1
2
3
4
5
6
7
8
9
10
11
12 public static void main(String[] args) {
int[] arr = new int[] { 1, 2, 3, 4 };
int[] newArr = dilatation(arr);
System.out.println(Arrays.toString(newArr));
}
private static int[] dilatation(int[] arr) {
// TODO Auto-generated method stub
int[] b = new int[arr.length * 2];
System.arraycopy(arr, 0, b, 0, arr.length);
return b;
}
二维数组
定义格式
格式1:
数据类型[][] 数组名 = new 数据类型[一维长度m][二维长度n];
- 表示二维数组的元素数量,即可以存放多少个一维数组
- 表示每一个一维数组,可以存放多少个元素
格式2:
数据类型[][] 数组名 = new 数据类型[一维长度m][];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 // 第一种格式
int[][] arr = new int[2][3];
System.out.println(arr); // [[I@b684286
/*
* [[I@b684286
*
* [[: 2个中括号就代表的是2维数组
* I: 数组中存储的数据类型为
* int 15db9742: 十六进制内存地址
*/
// 二维数组的每一个 元素都对应着(一维数组)地址
System.out.println(arr[0]); // [I@2a139a55
System.out.println(arr[1]); // [I@15db9742
//第二种定义格式
int[][] arr2 = new int[2][];
//输出arr2中2个元素值,默认为null、null
System.out.println(Arrays.toString(arr2));
//给二维数组的每个元素赋值
arr[0] = new int[2];
arr[1] = new int[3];
内存结构
- 一维数组内存结构:
- 二维数组内存结构:
可以把二维数组看成一个一维数组,数组的每个元素对应的内存区域中,存放的是一维数组引用值
元素访问
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 // int arr[m][n];
int[][] arr = new int[2][3];
// 存数
arr[0][0] = 11;
arr[0][1] = 22;
arr[0][2] = 33;
arr[1][0] = 11;
arr[1][1] = 22;
arr[1][2] = 33;
// 取数
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
// 注意:m、n的取值都是 [0,length-1] ,注意不要越界,否则会出现异常 ArrayIndexOutOfBoundsException
初始化
1
2
3
4
5 //第一种:完整格式
int[][] arr1 = new int[][]{{1,2,3},{4,5}};
//第二种:简化格式
int[][] arr2 = {{11, 22, 33}, {44, 55}};
综合案例
1
2
3
4 int[][] arr = new int[3][];
arr[0] = new int[]{10};
arr[1] = new int[]{20,20};
arr[2] = new int[]{30,30,30};
可变参数列表
JDK1.5或者以上版本中,可以使用可变参数列表
格式:
1
2
3 修饰符 返回值类型 方法名(数据类型... 参数名) {
方法体语句;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 //普通方法定义
public static void fun(int[] a){
//...
}
//可变参数列表 方法定义
public static void test(int... a){
//...
}
public static void main(String[] args) {
int[] arr = {1,2,3};
//普通方法的调用,只有下面一种形式
fun(arr);
//可变参数列表方法的调用,下面形式都可以
test(); //不传参
test(1); //传递1个元素
test(1,2,3,4); //传递多个元素
test(arr); //传递数组
}结论:可变参数列表本质上是一个数组,方法中使用可变参数列表,比用数组作参数功能更强大
补充:方法中有一个可变参数同时,还可以存在其他参数
1
2
3
4 public static void test(int a, int... b) {
System.out.println(a);
System.out.println(Arrays.toString(b));
}注意事项:可变参数和普通参数共存的时候,可变参数必须放到最后一个参数的位置。
总结:
- 可变参数列表可以接受 0-n个参数
- 可变参数列表还可以接受数组
- 可变参数列表必须放在函数参数列表的最右端,且只能出现1次
❤️❤️❤️忙碌的敲代码也不要忘了浪漫鸭!
业精于勤,荒于嬉;行成于思,毁于随。💪