# Java数组
[TOC]
## 导学
数组,这样一个概念,我们在之前的编程学习中也已经学习过了。数组是编程语言中最常用的一种**数据类型**。可以存储多个数据。数组本质上其实是一堆数的集合。
比如,我们想要保存30个类似的数据,如果不用数组的话,那么就需要设置30个变量来保存。而使用数组,我们只需要设置一个变量就可以了。
>[warning]数组是相同类型的数据按顺序组成的一种引用数据类型
## 数组的规范
* 存放的数据是相同的数据类型
* 数组的长度在定义时就确定了大小,数组是不可变长度的,或者说叫定长
* 数组中可以存放任意的数据类型(包含基本数据类型、引用数据类型、数组)
* 数组本身是引用数据类型(在栈内存中会存储其在堆内存中的引用地址)
* 数组会在内存中开辟一块连续的内存空间
## 一维数组
### 数组的定义
~~~
数据类型[] 变量名; // 强烈建议用这种命名
数据类型 变量名[]; // 只要知道就可以,c与c++是这种写法,要区分开来
~~~
对比之前变量的定义,我们发现,数组与变量的定义不同的地方在于数组的数据类型后面多了一个中括号。
### 数组的初始化(创建)
在 Java 语言中,**数组必须先被初始化,才能被使用**。所谓的初始化,就是在内存中为数组元素分配空间,并为每个元素赋予初始值。
* 静态初始化:显式的指定每个数组元素的值,由系统来决定数组的大小;
* 动态初始化:只需要指定数组的长度,通过程序动态的给每个元素赋值(即由系统为每个数组元素分配初始值)。
#### 静态初始化
语法:
~~~
type[] arrayName = {element1, element2,....}; // 比较常见
type[] arrayName = new type[]{element1, element2,...};
~~~
示例:
~~~
int[] arrs2;
arrs2 = new int[]{1, 2 ,3 ,4};
int[] arrs = {1, 2, 3, 4}; // 简写
~~~
该初始化方法,首先定义了数组的内容,同时也根据数组中内容的个数,决定了数组的长度
#### 动态初始化
语法:
~~~
数据类型[] 数组名= new 数据类型[数组长度];
~~~
示例:
~~~
int[] arr = new int[10];
int[] arr;
arr = new int[10];//表示我们创建了一个长度为10的整型数组
~~~
该初始化方法,首先定义了数组的长度,同时根据数据类型的默认值,来暂时确定了数组的内容。
#### 数组在内存中的存储与默认值
比如`int[] a = new int[5]`。a数组是一个整型数组,所以它会取数组的数据类型的默认值为自己的默认值。在此提前和大家说一下,int类型的默认值为0,所以a数组的默认值全部为0。
同时数组在内存中会开辟一块连续的内存空间。如下图所示:
![](https://img.kancloud.cn/63/dd/63dd7e356efa26d26f7a2d1d51764b7b_398x332.png)
### 数组元素的引用
语法:
~~~
数组名[下标]
~~~
>[info]数组中的索引(下标),通过 arrayName\[index\] 获取指定位置的数据,index 从 0 开始,最大值为 length-1
![](https://img.kancloud.cn/47/da/47daa7fcfde51091cbc9a9fbd24af25f_832x251.png)
我们不但可以通过索引来获取数组中元素的值,同时,我们也可以通过索引来改变数组中对应索引的元素的值。
示例
~~~
int[] arr = new int[10];
System.out.println(arr[0]);//0
arr[0] = 1;
System.out.println(arr[0]);//1
~~~
### 数组的长度
语法:
~~~
数组名.length
~~~
示例:
~~~
int[] a = new int[5];
System.out.println(a.length);//输出5
~~~
我们可以通过`.length`的形式来获取数组的长度。注意,这里的`.`代表着“的”这样一个意思,`length`表示数组的长度属性。
我们在之后的课程中会经常用到`.`,在其之后,可以跟着方法名,属性等等。
### 循环与数组
#### 普通循环
我们可以通过循环来为数组进行赋值和取值
* 通过数组索引方式对数组元素进行赋值时,使用数组**.length**属性作为 for 循环的条件。
* 在对数组元素进行操作时,一般使用 for 循环结构。
示例:
~~~
for (int i = 0; i < arrs3.length; i++) {
arrs3[i] = (i+1) * 10;
}
for (int i = 0; i < arrs3.length; i++) {//注意不要犯数组越界的错误
System.out.println(arrs3[i]);
}
~~~
#### 增强型for循环
增强型for循环又叫foreach循环,foreach循环在数组和之后学习的集合中有着重要的作用
~~~
for (数据类型 变量名 : 数组名| 集合名) {
element...
}
~~~
示例:
~~~
for(int a : arrs3) {
System.out.println(a);
}
~~~
>[danger]使用 foreach 一般情况下,只用作**遍历数据**,如果要对数组中元素进行修改,还是需要使用 for 循环带索引的方式进行,因为在上述的代码中,a 只是循环元素的一个副本
### 冒泡排序
首先我们来看一个问题,如何对一下,a与b的值进行交换
![](https://img.kancloud.cn/5e/6a/5e6a9c9baee8000edc472d9c6052db5c_566x241.png)
那么,如果我们在数组中存放了一组整数,想要对数组中数据进行由大到小的排序。
比如这样一组数:
![](https://img.kancloud.cn/4b/e8/4be8bca45a5734d28de3ab5c1d78427c_533x90.png)
思路:
1. 首先对数组中相邻的两个数进行比较,把数组元素从头到尾比较一次以后,我们希望能找出最大的那个值,放到数组的末尾。
2. 第二次进行比较的时候,找出第二大的值,放到数组的倒数第二位。
3. 随后进行第三次直到n次比较完成
![](https://img.kancloud.cn/ba/3f/ba3fee8de9a82c43322921e52c6d53c4_527x273.png)
![](https://img.kancloud.cn/f2/b3/f2b31e0a33b01d8e99b7bf001aaedc1a_526x209.png)
代码示例:
~~~
//冒泡排序法生成从小到大的排序方式
public class MaoPaoDemo {
public static void main(String[] args) {
int[] mina = { 34, 42, 33, 45, 6, 7 };
System.out.println("排序前的内容是:");
for (int n : mina) {
System.out.print(n + " ");
}
int temp;
for (int i = 0; i < mina.length - 1; i++) {
for (int n = mina.length-1; n > i; n--) {
if (mina[n] < mina[n - 1]) {
temp = mina[n - 1];
mina[n - 1] = mina[n];
mina[n] = temp;
}
}
}
System.out.println( '\n'+ "排序后的内容是:");
for (int j : mina) {
System.out.print(j+" ");
}
}
}
~~~
## 二维数组
在之前的课程中,我们也提到数组中可以放置基本数据类型和引用数据类型,尤其是数组中也可以放置数组。
### 二维数组的声明与创建
语法:
~~~
三种形式:
数据类型[][] 数组名
数据类型 数组名[][]
数据类型[] 数组名[]
~~~
示例:
~~~
int[][] arr;
int arr[][];
int[] arr[];
~~~
### 二维数组的初始化与引用
在学习二维数组的时候,我们需要知道二维数组存放的是什么样的数据;
如图:
![](https://img.kancloud.cn/c1/e4/c1e4fda30912a927b0b4d5f91516fbf4_690x146.png)
想要保存该类数据,就需要使用二维数组了。
所以,我们可以将二维数组看做一个几行几列的表格这样一个形式。
如果我们想要表示上述表格中的数据,就可以采用如下的方式
语法:
~~~
数据类型[][] 数组名;//先声明一个数组
数组名 = new 数据类型[长度][长度];//对数组进行初始化
或
数据类型[][] 数组名 = new 数据类型[长度][长度];//对数组声明的同时进行初始化
~~~
示例:
~~~
int[][] arr = new int[3][3];
~~~
![](https://img.kancloud.cn/64/de/64de2d1b142c895e10040806c42a3141_767x110.png)
~~~
//想要输出第三行第二列的数据:
System.out.println("arr[2][1]");
//为第二行第三列的数据赋值为9:
arr[1][2] = 9;
// 创建float类型的数组,只指定行数
// 注意:只指定行数的写法是可行的,但只指定列数和全不指定的写法是错误的
float arr1 = new float[3][];
// 因为没有指定列数,对该数组取值会出现空指针错误
//System.out.println(arr1[0][0]);
// 针对于该二维数组进行创建行
arr1[0] = new float[3];//第一行有三列,这样的写法可以指定每行有着不同的列
arr1[1] = new float[2];//第二行有二列
arr1[2] = new float[1];//第三行有一列
System.out.println(arr1[0][0]);//0.0
System.out.println(arr1[0][3]);//数组下标越界
~~~
以上使用的属于动态的初始化创建,接下来我们来看看静态的初始化创建。
语法:
~~~
数据类型[][] 数组名 = {{x,,x,x},{x,x},{x,x,x,x},...,{x}};
~~~
示例:
~~~
int[][] arr = {{1,2,3},{1,2,3},{1,2,3}};//三行三列的数组
或
int[][] arr = {{1},{1,2},{1,2,3}};//三行不同列的数组
~~~
引用:
~~~
System.out.println(arr[0][1]);//arr数组第一行第二列的元素
System.out.println(arr.length);//arr数组的长度
System.out.println(arr[0].length);//arr数组第一行的长度
//循环输出二维数组的内容
for(int i = 0; i < arr.length; i++) {
for(int t = 0; t < arr[i].length; t++) {
System.out.println(arr[i][t]);
}
}
~~~
## 练习
一、选择
1. 下列数组声明的语法格式不正确的是()
~~~
A. int[] array;
B. int array[];
C. char[];
D. String[] strArray;
~~~
2. 已知一个长度为10的数组b,数组b的第三个元素表示为?
~~~
A. b[3] B. b(3) C. b[2] D. b(2)
~~~
3. 当数组下标越界时,会发生()
~~~
A. 系统崩溃
B. 直接跳过
C. 抛出异常
D. 中止程序
~~~
4. 下面代码的运行结果为:()
![](https://img.kancloud.cn/73/5b/735bb8e79c4a2fcf1209ef92c8a7312e_455x180.png)
~~~
A. 55,8,5, B. 5,8,55, C. 8,5,55 D. 5,8,55
~~~
5. 下面代码的运行结果为:()
![](https://img.kancloud.cn/06/b5/06b5a06f120184fd212d53f8223912e5_444x171.png)
~~~
A. 4 B. 12 C. 0 D. 13
~~~
6. 下面程序的运行结果是?
![](https://img.kancloud.cn/04/dc/04dcb6e3588788ae876daa00a57ff176_446x157.png)
~~~
A. 30 B. 60 C. 50 D. 20
~~~
7. 以下关于二维数组创建对象的语法,错误的是?(多选)
~~~
A. char[][] ch=new char[][] ;
B. char ch[][]=new char[3][5];
C. char[] ch[]=new char[3][];
D. char[][] ch=new char[][5];
~~~
8. 下列哪个选项是给二维数组的第一行第一列的元素赋值的。
~~~
A. sum[][] = 3;
B. num[1][] = 3;
C. num[1][1] = 3;
D. sum[0][0] = 3;
~~~
9. 以下代码的输出结果为?
![](https://img.kancloud.cn/40/fd/40fdf0aef976564b7b67f05b7e93a2eb_447x106.png)
~~~
A. 2 4 B. 3 4 C. 3 3 D. 4 4
~~~
10. 下列数组有几行几列()
![](https://img.kancloud.cn/eb/58/eb5867068a2cf254b6b037a3ac3fbca9_443x57.png)
~~~
A. 三行五列
B. 五行五列
C. 三行三列
D. 五行三列
~~~
二、编程
1. 求数组中能被3整除的元素并打印输出。
数组内容:
![](https://img.kancloud.cn/62/23/6223bdde0433073b8e9db7a4584c37c7_320x152.png)
~~~
public class ArrayDemo {
public static void main(String[] args) {
//定义一个整型数组,并初始化
//循环遍历数组,找出能被3整除的元素并打印输出
}
}
~~~
2. 在一个二维数组中存放了三名学生的语文和数学的成绩,分别求语文和数学的总成绩及平均分并输出。
~~~
public class ScoreDemo{
public static void main(String[] args){
//定义一个三行两列的整型二维数组intArray
//自定义并保存三个学生的语文与数学成绩
//求语文的总成绩和平均分
//求数学的总成绩和平均分
}
}
~~~