数组
数组
一、为什么使用数组
如何存储100名学生的成绩?
- 方法:使用变量存储,重复声明100个double类型的变量。
- 缺点:麻烦,重复操作过多。
如何让100名学生成绩全部+1?
- 方法:100个变量重复相同的操作,直至全部完毕。
- 缺点:无法进行统一的操作。
通过上面的两个场景,很清楚地能了解到数组可以简化、统一操作。
二、数组的概念
概念:一组连续的存储空间,存储多个相同数据类型的值。
数组的创建
1
2
3
4
5
6public class TestCreateArray{
public static void main(String[] args){
//声明int数组类型变量a
int[] a = new int[5];//分配长度为5的连续空间
}
}数组的组成
- 数组中的每个数据格被称为“数组元素”。
- 对每个元素进行赋值或取值的操作被称为“元素的访问”。
- 访问元素时,需要使用“下标”(从0开始,依次+1,自动生成)
- 访问的语法:
数组名[下标];
例如,存:a[0]=10;
取:a[0]
。
数组的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class TestCreateArray{
public static void main(String[] args){
int[] a = new int[5];//创建数组
//依次赋值
a[0]=11;
a[1]=22;
a[2]=33;
a[3]=44;
a[4]=55;
//依次取值
System.out.println(a[0]);
System.out.println(a[1]);
System.out.println(a[2]);
System.out.println(a[3]);
System.out.println(a[4]);
}
}运行结果:
下标的范围
有效下标访问:
0~数组长度-1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class TestCreateArray{
public static void main(String[] args){
int[] a = new int[5];//创建数组
//依次赋值
a[0]=11;
a[1]=22;
a[2]=33;
a[3]=44;
a[4]=55;
//依次取值
System.out.println(a[0]);
System.out.println(a[1]);
System.out.println(a[2]);
System.out.println(a[3]);
System.out.println(a[4]);
System.out.println(a[5]);//无效下标,数组越界
}
}运行结果:
当运行到这一行代码的时候,出现数组下标溢出异常。
数组的遍历
从头到尾,逐一对数组的每个元素进行访问。
数组名.length
可动态获得数组长度。1
2
3
4
5
6
7
8
9
10
11
12
13
14public class TestVisitArray{
public static void main(String[] args){
int[] a = new int[5];
a[0]=11;
a[1]=22;
a[2]=33;
a[3]=44;
a[4]=55;
//数组遍历
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
}
}运行结果:
数组的默认值
在没有为数组元素赋值的情况下,依旧可以正确访问。整数数组的默认值为
0
;1
2
3
4
5整数:0
小数:0.0
字符:\u0000
布尔:false
其他(引用数据类型):null1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24public class TestDefaultValue{
public static void main(String[] args){
int[] a = new int[5];
for(int i=0;i<a.length;i++){
System.out.println(a[i]);
}
double[] b = new double[5];
for(int i=0;i<b.length;i++){
System.out.println(b[i]);
}
char[] c = new char[5];
for(int i=0;i<c.length;i++){
System.out.println("#"+c[i]+"#");
}
boolean[] d = new boolean[5];
for(int i=0;i<d.length;i++){
System.out.println(d[i]);
}
String[] e = new String[5];
for(int i=0;i<e.length;i++){
System.out.println(e[i]);
}
}
}运行结果:
三、数组创建的几种方式
先声明、再分配空间
1
2数据类型[] 数组名;
数组名 = new 数据类型[长度];声明并分配空间
1
数据类型[] 数组名 = new 数据类型[长度];
声明并赋值(繁琐)
1
2
3
4
5
6数据类型[] 数组名 = new 数据类型[]{value1,value2,value3,...};
/*
这种方式可先声明后赋值
数据类型[] 数组名;
数组名 = new 数据类型[]{value1,value2,value3,...};
*/声明并赋值(简单)
1
2
3
4
5
6数据类型[] 数组名 = {value1,value2,value3,...};
/*
注意这种方式不可先声明后赋值
数据类型[] 数组名;
数组名 = {value1,value2,value3,...};
*/
案例1:给定一个整数数组,统计数组中所有元素的平均值。
1 | public class TestAvg{ |
运行结果:
案例2:给定一个整数数组,读入一个整数n,如果n在数组中存在,输入下标,不存在则输出-1
1 | import java.util.Scanner; |
运行结果:
四、数组的扩容
创建数组时,必须显示指定长度,并在创建之后不可更改长度。
扩容的思路:
- 创建大于原数组长度的新数组。
- 将原数组中的元素依次复制到新数组中。
复制的方式
循环将原数组中所有元素逐一赋值给新数组。
System.arraycopy(原数组,原数组起始,新数组,新数组起始,长度);
。从原数组起始位置复制长度个元素,从新数组起始位置开始赋值给新数组。
java.util.Arrays.copyOf(原数组,新数组长度);//返回带有原值的新数组。
案例1:循环赋值
1 | public class TestArrCopy{ |
运行结果:
案例2:System.arraycopy();
1 | public class TestArrCopy{ |
运行结果:
案例3:java.util.Arrays.copyOf(原数组,新数组长度);
这个工具方法会根据指定的新数组长度会初始化指定长度的数组,并将原数组的值赋给新数组后,返回新数组。
1 | import java.util.Arrays; |
运行结果:
数组作为引用类型之一,其变量中存储的是数组的地址。
五、数组类型的参数
1 | public class TestArrayParameter{ |
假设arr
的地址为0x0000A001
;参数传入后oneArray
的地址为0x0000A001
。
printArr方法调用时,将arr中的地址赋给了oneArray,此时二者指向同一个数组。
运行结果:
传递参数时,基本类型传递的是变量中的值,引用类型传递的是变量中的地址。
六、数组类型的返回值
1 | public class TestReturnValue{ |
假设arr1
的地址为0x0000a001
,调用函数expand
传给oldArr
的地址为0x0000a001
,在函数内部给newArray
new了一个新的地址,并将oldArr
的值逐个赋给newArray
,假设newArray
的地址为0x0000a002
,函数的返回值也是这个,于是arr2
的值也是0x0000a002
。
运行结果:
调用数组类型返回值的方法时,方法执行后,返回的是数组的地址。
七、可变长参数
概念:可接受多个同类型的实参,个数不限,使用方式与数组相同。
语法:数据类型...形参名
必须定义在形参列表的最后,且只能有一个。
1 | public class variableArguments{ |
运行结果:
八、Arrays 类
java.util.Arrays
类能方便地操作数组,它提供的所有方法都是静态的。
九、二维数组
概念:一维数组中的一维数组;数组中的元素,还是数组。
1.二维数组的赋值
1 | public class Test2DArray{ |
2.二维数组的访问
1 | public class Test2DArray{ |
运行结果:
3.二维数组创建的几种方式
动态初始化
1 | 数据类型 数组名[][] = new 数据类型[m][n] |
先声明,再分配空间:
1
2数据类型[][] 数组名;
数组名 = new 数据类型[高维长度][多维长度];声明并分配空间:
1
数据类型[][] 数组名 = new 数据类型[高维长度][多维长度];
静态初始化
1 | 数据类型 [][] 数组名= {{元素1,元素2....},{元素1,元素2....},{元素1,元素2....}.....}; |
静态初始化可用于不规则二维数组的初始化
声明并赋值
1
2
3数据类型[][] 数组名 = new 数据类型[][]{{v1,v2,v3},{v4,v5,v6}};
或
数据类型[][] 数组名 = {{v1,v2,v3},{v4,v5,v6}};