數組
概念:數組(Array),是多個相同類型數據按一定順序排列 的集合,並使用一個名字命名,並通過編號的方式對這些數據進行統一管理。簡單來說數組就是一個容器。將多個數據存儲到一起,每個數據稱爲該容器的元素。生活中的容器:水杯,衣櫃,教室。數組就是存儲數據長度固定的容器,保證多個數據的數據類型要一致。
數組的特點
- 數組本身是引用數據類型,而數組中的元素可以是任何數據類型,包括基本數據類型和引用數據類型。
- 創建數組對象會在內存中開闢一整塊連續的空間,而數組名中引用的是這塊連續空間的首地址。
- 數組的長度一旦確定,就不能修改。
- 我們可以直接通過下標(或索引)的方式調用指定位置的元素,速度很快。
- 數組的分類: 按照維度:一維數組、二維數組、三維數組、… 按照元素的數據類型分:基本數據類型元素的數組、引用數據類型元素的數組(即對象數組)
數組的初始化
- 在內存當中創建一個數組,並且向其中賦予一些默認值。
兩種常見的初始化方式:
- 動態初始化(指定長度):數組聲明且爲數組元素分配空間與賦值的操作分開進行
- 靜態初始化(指定內容):在定義數組的同時就爲數組元素分配空間並賦值。
數組的定義
方式一:動態初始化數組
格式:
- 數組存儲的數據類型[ ] 數組名字 = new 數組存儲的數據類型[長度];
格式詳解:
- 數組存儲的數據類型: 創建的數組容器可以存儲什麼數據類型。
- [ ] : 表示數組。
- 數組名字:爲定義的數組起個變量名,滿足標識符規範,可以使用名字操作數組。
- new:關鍵字,創建數組使用的關鍵字。
- 數組存儲的數據類型: 創建的數組容器可以存儲什麼數據類型。
- [長度]: 數組的長度,表示數組容器中可以存儲多少個元素。
注意:
- 數組有定長特性,長度一旦指定,不可更改。 和水杯道理相同,買了一個2升的水杯,總容量就是2升,不能多也不能少。
舉例:
//定義可以存儲3個整數的數組容器
int[] arr = new int[3];
方式二:靜態初始化基本格式
格式:
- 數據類型[] 數組名 = new 數據類型[]{元素1,元素2,元素3...};
示例:
//定義存儲1,2,3,4,5整數的數組容器。
int[] array = new int[]{1,2,3,4,5};
注意事項:
- 雖然靜態初始化沒有直接告訴長度,但是根據大括號裏面的元素具體內容,也可以自動推算出來長度。
方式三:靜態初始化數組的省略格式
格式:
- 數據類型[] 數組名 = {元素1,元素2,元素3...};
//定義存儲1,2,3,4,5整數的數組容器
int[] array1 = {1,2,3,4,5};
注意事項:
- 靜態初始化沒有直接指定長度,但是仍然會自動推算得到長度。
- 靜態初始化標準格式可以拆分成爲兩個步驟。
- 動態初始化也可以拆分成爲兩個步驟。
- 靜態初始化一旦使用省略格式,就不能拆分成爲兩個步驟了。
使用建議:
- 如果不確定數組當中的具體內容,用動態初始化;否則,已經確定了具體的內容,用靜態初始化。
代碼演示
public class DemoArrayNotice {
public static void main(String[] args) {
// 省略格式的靜態初始化
int[] arrayA = {10, 20, 30};
// 靜態初始化的標準格式,可以拆分成爲兩個步驟
int[] arrayB;
arrayB = new int[]{11, 21, 31};
// 動態初始化也可以拆分成爲兩個步驟
int[] arrayC;
arrayC = new int[5];
// 靜態初始化的省略格式,不能拆分成爲兩個步驟。
// int[] arrayD;
// arrayD = { 10, 20, 30 };
}
}
一維數組的使用
索引: 每一個存儲到數組的元素,都會自動的擁有一個編號,從0開始,這個自動編號稱爲數組索引(index),可以通過數組的索引訪問到數組中的元素。格式:數組名[數組元素下標]
- 數組元素下標可以是整型常量或整型表達式。如a[3] , b[i] , c[6*i];
- 數組元素下標從0開始;長度爲n的數組合法下標取值範圍: 0 —>n-1;如int a[]=new int[3]; 可引用的數組元素爲a[0]、a[1]、a[2]
數組的長度屬性: 每個數組都具有長度,而且是固定的,Java中賦予了數組的一個屬性,可以獲取到數組的長度,語句爲: 數組名.length ,屬性length的執行結果是數組的長度,int類型結果。由次可以推斷出,數 組的最大索引值爲 數組名.length-1 。
- 爲數組中的元素賦值 格式:數組名[索引]=數值
- 獲取出數組中的元素 格式:變量=數組名[索引]
- 獲取數組元素的個數 格式:數組名.length
代碼示例
package demo01;
/*
直接打印數組名稱,得到的是數組對應的:內存地址哈希值。
訪問數組元素的格式:數組名稱[索引值]
索引值:就是一個int數字,代表數組當中元素的編號。
【注意】索引值從0開始,一直到“數組的長度-1”爲止。
*/
public class Demo04ArrayUse {
public static void main(String[] args) {
// 靜態初始化的省略格式
int[] array = { 10, 20, 30 };
System.out.println(array); // [I@75412c2f
// 直接打印數組當中的元素
System.out.println(array[0]); // 10
System.out.println(array[1]); // 20
System.out.println(array[2]); // 30
// 也可以將數組當中的某一個單個元素,賦值交給變量
int num = array[1];
System.out.println(num); // 20
}
}
數組的默認值
數組是引用類型,它的元素相當於類的成員變量,因此數組一經 分配空間,其中的每個元素也被按照成員變量同樣的方式被隱式 初始化。簡而言之:數組創建之後系統就會給它分配一個默認值。不同類型的數組有不同的默認值,如下圖所示:
代碼示例
package demo01;
/*
使用動態初始化數組的時候,其中的元素將會自動擁有一個默認值。
注意事項:
靜態初始化其實也有默認值的過程,只不過系統自動馬上將默認值替換成爲了大括號當中的具體數值。
*/
public class Demo05ArrayUse {
public static void main(String[] args) {
// 動態初始化一個數組
int[] array = new int[3];
System.out.println(array); // [I@50cbc42f
System.out.println(array[0]); // 0
System.out.println(array[1]); // 0
System.out.println(array[2]); // 0
// 將數據123賦值交給數組array當中的1號元素
array[1] = 123;
System.out.println(array[0]); // 0
System.out.println(array[1]); // 123
System.out.println(array[2]); // 0
}
}
數組原理內存圖
內存概述:內存是計算機中的重要原件,臨時存儲區域,作用是運行程序。我們編寫的程序是存放在硬盤中的,在硬盤中的程序是不會運行的,必須放進內存中才能運行,運行完畢後會清空內存。 Java虛擬機要運行程序,必須要對內存進行空間的分配和管理。
Java虛擬機的內存劃分
爲了提高運算效率,就對空間進行了不同區域的劃分,因爲每一片區域都有特定的處理數據方式和內存管理方式。
JVM的內存劃分:
每個區域的具體作用如下所示
數組在內存中的存儲
觀察下面代碼
package demo02;
public class Demo01ArrayOne {
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr);//[I@5f150435 }
}
}
以上方法執行,輸出的結果是[I@5f150435,這個是什麼呢?是數組在內存中的地址。new出來的內容,都是在堆 內存中存儲的,而方法中的變量arr保存的是數組的地址。 輸出arr[0],就會輸出arr保存的內存地址中數組中0索引上的元素
多維數組的使用
- Java 語言裏提供了支持多維數組的語法。
- 對於二維數組的理解,我們可以看成是一維數組 array1又作爲另一個一維數組array2的元素而存 在。其實,從數組底層的運行機制來看,其實沒有多維數組。
定義二維數組的方式
格式1(動態初始化):數據類型[ ] [ ] 數組名稱 = new 數據類型[ 二維數組中一維數組的個數][ 一維數組中元素的個數];
package demo02;
public class Demo01ArrayOne {
public static void main(String[] args) {
/*
定義了名稱爲arr的二維數組
二維數組中有3個一維數組
每一個一維數組中有2個元素
一維數組的名稱分別爲arr[0], arr[1], arr[2]
*/
int[][] arr = new int[3][2];
// 給第一個一維數組1腳標位賦值爲78:
arr[0][1] = 78;
}
}
格式2(動態初始化):數據類型[ ] [ ] 數組名稱 = new 數據類型[ 二維數組中一維數組的個數][ ];
package demo02;
public class Demo02ArrayTwo {
public static void main(String[] args) {
/*
二維數組中有3個一維數組。
每個一維數組都是默認初始化值null (注意:區別于格式1)
注:int[][]arr = new int[][3]; //非法
*/
int[][] arr = new int[3][];
//對這個三個一維數組分別進行初始化
arr[0] = new int[3];
arr[1] = new int[1];
arr[2] = new int[2];
}
}
格式3(靜態初始化):數據類型[ ] [ ] 數組名稱 = new 數據類型[ ][ ]{{具體的元素},{具體的元素},{具體的元素}};
package demo02;
public class Demo03ArraySame {
public static void main(String[] args) {
/*
定義一個名稱爲arr的二維數組,二維數組中有三個一維數組
每一個一維數組中具體元素也都已初始化
*/
int[][] arr = new int[][]{{3, 8, 2}, {2, 7}, {9, 0, 1, 6}};
//第一個一維數組
arr[0] = new int[]{3, 8, 2};
//第二個一維數組
arr[1] = new int[]{2, 7};
//第三個一維數組
arr[2] = new int[]{9, 0, 1, 6};
//第三個一維數組的長度表示方式
int length = arr[2].length;
System.out.println(length);//4
}
}
使用數組的常見錯誤
越界異常
int[] arr = {1,2,3};
System.out.println(arr[3]);
創建數組,賦值3個元素,數組的索引就是0,1,2,沒有3索引,因此我們不能訪問數組中不存在的索引,程序運行後,將會拋出 ArrayIndexOutOfBoundsException 數組越界異常。在開發中,數組的越界異常是不能出現的,一 旦出現了,就必須要修改我們編寫的代碼。
數組空指針異常
int[] arr = {1,2,3};
arr = null;
System.out.println(arr[0]);
arr = null 這行代碼,意味着變量arr將不會在保存數組的內存地址,也就不允許再操作數組了,因此運行的時候 會拋出 NullPointerException 空指針異常。在開發中,數組的越界異常是不能出現的,一旦出現了,就必須要修 改我們編寫的代碼。
對數組的常見操作
遍歷一維數組
package demo03;
/*
遍歷數組,說的就是對數組當中的每一個元素進行逐一、挨個兒處理。默認的處理方式就是打印輸出。
*/
public class Demo04Array {
public static void main(String[] args) {
int[] array = { 15, 25, 30, 40, 50, 60, 75 };
// int len = array.length; 獲取數組元素的個數
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
遍歷二維數組
package demo03;
public class Demo {
public static void main(String[] args) {
//1.定義二維數組
int[] arr[] = new int[][]{{1, 2, 3}, {4, 5, 9, 10}, {6, 7, 8}};
//2.如何調用數組的指定位置的元素
System.out.println(arr[0][1]);//2
System.out.println(arr[1][1]);//5
//3.獲取二維數組中一維數組數組的個數
System.out.println(arr.length);//3
//4.獲取二維數組中一維數組數組的長度
System.out.println(arr[0].length);//3
System.out.println(arr[1].length);//4
//5.如何遍歷二維數組
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();
}
}
}
數組獲取最大值元素
package demo03;
public class Demo05ArrayMax {
public static void main(String[] args) {
int[] array = { 5, 15, 30, 20, 10000, 30, 35 };
int max = array[0]; //定義變量,保存數組中0索引的元素
for (int i = 1; i < array.length; i++) {
//如果數組元素大於max
if (array[i] > max) {
//max記錄住大值
max = array[i];
}
}
System.out.println("最大值:" + max);
}
}
數組的反轉
- 數組中的元素顛倒順序,例如原始數組爲1,2,3,4,5,反轉後的數組爲5,4,3,2,1
實現思想:數組最遠端的元素互換位置。
- 實現反轉,就需要將數組最遠端元素位置交換
- 定義兩個變量,保存數組的最小索引和最大索引
- 兩個索引上的元素交換位置
- 最小索引++,最大索引--,再次交換位置
- 最小索引超過了最大索引,數組反轉操作結束
package demo03;
/*
數組元素的反轉:
本來的樣子:[1, 2, 3, 4]
之後的樣子:[4, 3, 2, 1]
要求不能使用新數組,就用原來的唯一一個數組。
*/
public class Demo07ArrayReverse {
public static void main(String[] args) {
int[] array = {10, 20, 30, 40, 50};
/*
初始化語句:int min = 0, max = array.length - 1
條件判斷:min < max
步進表達式:min++, max--
循環體:用第三個變量倒手
*/
for (int min = 0, max = array.length - 1; min < max; min++, max--) {
int temp = array[min];
array[min] = array[max];
array[max] = temp;
}
}
}