Java数组
一维数组
数组是一种分组管理数据的语言结构,借助数组可以有序地创建、存储、访问一组独立的值,数组是一个值列表,每个值连续存储在由数组开辟的一块空间之内。数组作为一种引用数据类型,应将其分两部分看,一部分为在栈中的引用地址,另一部分为在堆中的实际值,栈中的引用地址指向堆中实际值。
数组的声明与定义
int[] arr = {1,2,3};//将变量arr定义为整型数组,并为其赋初值;
int[] brr;
brr = new int[4];//声明brr为整型数组,开辟16字节的空间,初值都为0;
int crr[] = {1,2,3};//定义crr[]为整型;
int drr = new int[]{1,2,3,4}//声明整型同时赋初值;
此时arr, crr中含有相同的初值,用System.out.print(arr + “ ” + crr);一个语句来直接打印出arr与crr的地址,得到的结果是[I@3f3afe78 [I@7f63425a,其中I代表整型数组,而后面的代码不相同,说明arr和crr分别存储在不同的区域,java数组在栈中存放引用地址,而在堆中申请连续内存来保存具体数字,此时改变一个数组中一个值并不影响另一个数组对应的值。
如果:
int[] arr = {1,2,3};
int[] brr = arr;
则相当于将arr地址赋给brr,两者的地址对应的具体内容都相等,改变一个数组中一个值便等同于改变另一个值。
另外,java数组的长度不必为常量,可以先创造一个整型变量接收输入的值,再声明一个数组长度为变量的数组。
java对越界要求严格在数组中必不能越界,否则报错。
数组遍历
1、 for循环 for(int i = 0;i < arr.length;i++){};//以arr为例,
2、 foreach循环:
for(int i:arr){
System.out.print(i + “ ”);//以arr和打印数组为例;
}
在这里的i即为arr中的元素,而非在for循环中常使用的数组元素下标。
3、 Arrays.toString(数组名);调用该方法,将整个数组中值转为String类型,打印数组过程中若print()方法中放数组名则出现一串代码,在print()中调用此方法可直接打出数组。
数组拷贝
1、 for循环 新数组中每个元素通过for循环逐个被赋值。
2、 数组名.clone()方法
3、 Arrays.copyof()方法 括号中需指明源数组和新数组截取源数组长度,若新数组超过源数组长度,自动补0;
int arr[] = {1,2,3};
int brr[] = Arrays.copyOf(arr, arr.length);
4、 System.arraycopy()方法 此方法源数组和新数组必须事先定义好,五个参数分别为源数组、源数组起始下标、新数组、新数组起始下标、拷贝长度。
int[] arr = {1,2,3};
int[] brr = new int[3];
System.arraycopy(arr, 0, brr, 0, arr.length);
以上方法都能实现数组的复制,通过值传递,实现了深拷贝,即改变一个数组中值,不会影响另一个数组中值,通过Arrays.copyof()方法可以调整后得到的数组长度,实现数组的扩容和缩容。另外,数组所存储的值存储在堆中,将整个数组作为参数传递给方法时,实际传递的是一个原数组对象引用的拷贝,引用对象所指向的仍为原数组在堆中的实际值,借此仍可实现对原数组的操作。例如:
public static void main(String[] args){
int[] arr = new int[2]; //在main方法中定义arr
change(arr); //arr作为形参传递给change方法
System.out.println(Arrays.toString(arr)); //结果为[1, 0]
}
public static void change(int[] arr){
arr[0] = 1; //给被调用的数组首元素赋值1
}
可以实现main方法中arr[0]为1。
二维数组
在逻辑上可认为二维数组的元素都是一维数组,从而使得二维数组可以存储一个矩阵,而一位数组在二维数组中存储的实际值是存储其引用地址,而不是将存储在二维数组中的一位数组中真实的值存储进去,而是通过访问存储在二维数组中的一位数组中地址达到访问二维数组中一位数组的值的效果。二维数组指向一位数组地址,一位数组地址指向实际值。
java的二维数组在定义时可以不声明第二维的长度,同一数组的第二维数组长度也不必一样,从而可实现交错数组。
二维数组的声明和定义
int[][] arr = new int[][];//方括号组的个数代表数组维数;
二维数组的遍历
1、两层for循环
2、两层foreach
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
for (int[] i:arr) {
for (int j: i) {
System.out.print(j); //实现打印各个元素
}
}
i为arr下的每个一维数组,j为一维数组中的每个元素。
4、 Arrays.deepToString方法实现将二维数组转为字符串,适用于多维数组。
二维数组的拷贝
1、 两层for循环或两层foreach对新数组元素依次赋值,由于数组事先定义,两数组地址不同,属于深拷贝。
2、 外层for循环内层Arrays.copyOf()或System.arraycopy(),深拷贝。
3、 直接拷贝二维数组值,由于二维数组实质上是存放着一组一位数组引用地址的一位数组,所以存放在堆中的实际值通过新数组和原数组都能进行改变,改变一个,再用另一个访问,便会得到变化的值,属于浅拷贝。
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
int[][] brr;
brr = Arrays.copyOf(arr, arr.length);
arr[0][0] = 100;
System.out.println(brr[0][0]);
此时输出brr[0][0]也为100。