# 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。
同時數組在內存中會開辟一塊連續的內存空間。如下圖所示:

### 數組元素的引用
語法:
~~~
數組名[下標]
~~~
>[info]數組中的索引(下標),通過 arrayName\[index\] 獲取指定位置的數據,index 從 0 開始,最大值為 length-1

我們不但可以通過索引來獲取數組中元素的值,同時,我們也可以通過索引來改變數組中對應索引的元素的值。
示例
~~~
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的值進行交換

那么,如果我們在數組中存放了一組整數,想要對數組中數據進行由大到小的排序。
比如這樣一組數:

思路:
1. 首先對數組中相鄰的兩個數進行比較,把數組元素從頭到尾比較一次以后,我們希望能找出最大的那個值,放到數組的末尾。
2. 第二次進行比較的時候,找出第二大的值,放到數組的倒數第二位。
3. 隨后進行第三次直到n次比較完成


代碼示例:
~~~
//冒泡排序法生成從小到大的排序方式
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[];
~~~
### 二維數組的初始化與引用
在學習二維數組的時候,我們需要知道二維數組存放的是什么樣的數據;
如圖:

想要保存該類數據,就需要使用二維數組了。
所以,我們可以將二維數組看做一個幾行幾列的表格這樣一個形式。
如果我們想要表示上述表格中的數據,就可以采用如下的方式
語法:
~~~
數據類型[][] 數組名;//先聲明一個數組
數組名 = new 數據類型[長度][長度];//對數組進行初始化
或
數據類型[][] 數組名 = new 數據類型[長度][長度];//對數組聲明的同時進行初始化
~~~
示例:
~~~
int[][] arr = new int[3][3];
~~~

~~~
//想要輸出第三行第二列的數據:
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. 下面代碼的運行結果為:()

~~~
A. 55,8,5, B. 5,8,55, C. 8,5,55 D. 5,8,55
~~~
5. 下面代碼的運行結果為:()

~~~
A. 4 B. 12 C. 0 D. 13
~~~
6. 下面程序的運行結果是?

~~~
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. 以下代碼的輸出結果為?

~~~
A. 2 4 B. 3 4 C. 3 3 D. 4 4
~~~
10. 下列數組有幾行幾列()

~~~
A. 三行五列
B. 五行五列
C. 三行三列
D. 五行三列
~~~
二、編程
1. 求數組中能被3整除的元素并打印輸出。
數組內容:

~~~
public class ArrayDemo {
public static void main(String[] args) {
//定義一個整型數組,并初始化
//循環遍歷數組,找出能被3整除的元素并打印輸出
}
}
~~~
2. 在一個二維數組中存放了三名學生的語文和數學的成績,分別求語文和數學的總成績及平均分并輸出。
~~~
public class ScoreDemo{
public static void main(String[] args){
//定義一個三行兩列的整型二維數組intArray
//自定義并保存三個學生的語文與數學成績
//求語文的總成績和平均分
//求數學的總成績和平均分
}
}
~~~