數組
文章目錄
1、數組的相關概念和名詞(瞭解)
1、數組(array):
數組(array):簡單的說,就是一組數, 一組具有相同數據類型的數,是按照一定順序排列的集合。
當一組數據的數據類型,意義是一樣的時候,那麼爲了方便的統一的管理它們,我們需要用新的數據的存儲結構來進行存儲。例如:數組。
所謂數組(Array),就是相同數據類型的元素按一定順序排列的集合,就是把有限個類型相同的變量用一個名字命名,以便統一管理他們,然後用編號區分他們,這個名字稱爲數組名,編號稱爲下標或索引(index)。
組成數組的各個變量稱爲數組的元素(element)。數組中元素的個數稱爲數組的長度(length)。
數組
- 是一組具有相同數據類型的數據按照一定順序排列的集合。
- 把有限的幾個相同類型的變量使用一個名稱來進行統一管理。
2、數組名:
(1)這個數組名,代表的是一組數
(2)這個數組名中存儲的整個數組的“首地址”
int[] scores = new int[3];
scores[0] = 100;
//數組名:例如:scores
3、下標(index):
我們使用編號、索引、下標來區別表示一組數當中某一個。
範圍:[0,數組長度-1]
例如:遍歷 for(int i = 0; i<arr.length; i++){}
int[] scores = new int[3];
scores[0] = 100;
//數組名:例如:scores
//下標:範圍:[0,長度-1]
// 例如:[0]
4、元素(element):
這一組中的每一個數據都是元素。
如何表示數組元素? 數組名[下標]
int[] scores = new int[3];
scores[0] = 100;
//數組名:例如:scores
//下標:範圍:[0,長度-1]
// 例如:[0]
//元素:數組名[下標]
// 例如:scores[0]
5、數組的長度(length)
數組中元素的總個數。
如何獲取數組長度? 數組名.length
int[] scores = new int[3];
scores[0] = 100;
//數組名:例如:scores
//下標:範圍:[0,長度-1]
// 例如:[0]
//元素:數組名[下標]
// 例如:scores[0]
//數組的長度:元素的總個數,可以這麼表示: 數組名.length
數組、數組名、下標、元素、長度等名詞瞭解就行,溝通的方便。
爲什麼要用數組呢?我用變量存儲不香嗎?
變量存儲那麼多不麻煩嗎?聲明、變量名、變量值,計算處理都不方便。
eg:
class Test01_Array{
public static void main(String[] args){
/*
要存儲本組學員的成績,例如:第1組,有5個同學
*/
/*
int score1 = 100;
int score2 = 90;
int score3 = 80;
int score4 = 70;
int score5 = 60;
//用5個變量存儲沒問題,但是如果涉及到對數據的管理:例如,求最值,排序等,就非常麻煩
*/
int[] scores = new int[5];//用scores這一個統一的名稱,來管理5個int類型的元素
scores[0] = 100;//每一個元素都有自己的下標,編號,索引
scores[1] = 90;
scores[2] = 80;
scores[3] = 70;
scores[4] = 60;
// scores[6] = 50;// java.lang.ArrayIndexOutOfBoundsException:數組下標越界異常
System.out.println(scores.length);
for (int i = 0; i < scores.length; i++) {
System.out.print(scores[i] + "\t");
}
}
}
Result
5
100 90 80 70 60
Process finished with exit code 0
2 、數組的相關語法
2.1、 數組的聲明
語法格式:
public class Test01_Review{
public static void main(String[] args){
//推薦
int[] arr1;//在Java中int[]是一種引用數據類型,是數組類型
//也對,但是不推薦
int arr2[];
//最早的時候,C語言不提對象的概念,所以沒有把int[]看成一種數據類型,
//只是強調一組數,而最重要的是這組數據的類型是int類型
//int[] arr = new int[5]{1,2,3,4,5};//錯誤的
}
}
示例:
//要存儲一組整數
int[] array;
//要存儲一組單字符
char[] array;
//要存儲一組字符串
String[] array;
數組
//數組的聲明 原則:先聲明後使用
//聲明一個數組?
//語法格式;
//元素的數據類型[] 數組名;
class Test02_ArrayDefineAndUse{
public static void main(String[] args){
//(1)聲明一個數組,用來存儲幾個學員的成績
int[] scores;
//(2)初始化數組
//靜態初始化
//數組名 = new 元素的數據類型[]{元素的值列表};
scores = new int[]{89,45,67,88,90};
//如果把數組的聲明與靜態初始化合成一句
//int[] scores = new int[]{89,45,67,88,90};
//甚至還可以簡化:
//int[] scores = {89,45,67,88,90};
System.out.println("數組的長度:" + scores.length);
//(3)遍歷數組
//下標index的範圍:[0,長度-1]
//下標index的範圍:[0,scores.length-1]
for(int index = 0; index<scores.length; index++){
//每一個元素,就是數組名[下標]
System.out.println(scores[index]);
}
}
}
回憶: 變量的聲明與使用 (1)變量的聲明 數據類型 變量名; (2)變量的初始化 變量名 = 變量值; 聲明和初始化合成一句 數據類型 變量名 = 變量初始值;
exercise
/*
2、數組的練習2:
用一個數組,保存平年1-12月的滿月天數,並且遍歷顯示結果:
1月:31天
2月:28天
...
*/
class Test04_Exer2{
public static void main(String[] args){
//用一個數組,保存平年1-12月的滿月天數,
int[] daysOfMonth = {31,28,31,30,31,30,31,31,30,31,30,31};
//並且遍歷顯示結果
for(int i=0; i<daysOfMonth.length; i++){
// System.out.println((i+1) + "月:" + daysOfMonth[i]);
System.out.print((i+1) + "月:" + daysOfMonth[i] + "\t");
}
}
}
/*
3、數組的練習3:
用一個數組,保存星期一到星期天的7個英語單詞,
從鍵盤輸入1-7,顯示對應的單詞
*/
class Test05_Exer3{
public static void main(String[] args){
//用一個數組,保存星期一到星期天的7個英語單詞,
String[] weeks = {"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
// 從鍵盤輸入1-7,顯示對應的單詞
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.print("請輸入星期(1-7):");
int week = input.nextInt();
if(week<1 || week>7){
System.out.println("輸入有誤!");
}else{
//week對應的英語單詞在weeks數組中
//week=1,weeks[0]
//week=2,weeks[1]
//...
System.out.println(week+"對應的星期的單詞是:" + weeks[week-1]);
}
//Result
//請輸入星期(1-7):7
//7對應的星期的單詞是:Sunday
//
//Process finished with exit code 0
}
}
2.2、 數組的初始化
數組初始化的目的:
(1)確定數組的長度。
(2)爲元素賦值,就是確定數組的元素的值。
兩種初始化方式:
1、動態初始化
語法格式:
//指定數組長度
數組名 = new 元素的數據類型[長度];
//爲元素賦值
數組名[下標] = 值; //這個值可以是個常量值,也可以是個表達式的計算結果,也可以是鍵盤輸入的
//如果每個元素的賦值比較有規律,通常使用for循環賦值
for(int i=0; i<長度; i++){
數組名[下標] = 值;
//數組名[i] = 值;
}
問:如果只指定數組長度,沒有爲元素手動賦值,那麼元素有值嗎?
有默認值
(1)基本數據類型
byte,short,int,long:0
float,double:0.0
char:\u0000
boolean:false
(2)引用數據類型
統統都是null
沒有爲元素手動賦值,那麼元素有值嗎?
有默認值
基本的 0,0.0,\u0000,false
引用數據類型
統統都是null的
2、靜態初始化
語法格式:
數組名 = new 元素的數據類型[]{值列表};
//int[] arr = new int[5]{1,2,3,4,5};//錯誤的
//更簡潔
//當聲明與靜態初始化一起完成時,可以簡化
元素的數據類型[] 數組名 = {值列表};
靜態初始化
適用場合:
當數組的元素是已知的有限個時,可以使用靜態初始化。
示例代碼:
String[] weeks = {"monday","tuesday","wednesday","thursday","friday","saturday","sunday"};
int[] daysOfMonths = {31,28,31,30,31,30,31,31,30,31,30,31};
char[] letters = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
數組的元素是已知的有限個時,可以使用靜態初始化。
/*
數組的定義和初始化、使用的方式二:
1、數組的聲明?不變
元素的數據類型[] 數組名;
2、數組的初始化
(1)確定數組的長度
(2)確定數組的元素的值
方式一:靜態初始化
數組名 = new 元素的數據類型[]{元素的值列表};
說明:(1)數組的長度由{}中的值的個數決定。
(2)元素的值,在{}中直接指定
方式二:動態初始化
數組名 = new 元素的數據類型[長度];
說明:(1)數組的長度在[]指定
(2)如果沒有手動賦值之前,數組的元素有默認值
元素是基本數據類型:
byte,short,int,long:0
float,double:0.0
char:\u0000 字符編碼爲0的空字符
boolean:false
元素是引用數據類型:null
(3)給元素手動賦值
如果沒有什麼規律,就一個一個賦值;
如果有規律,可以使用循環賦值;
3、如何表示數組的長度?
數組名.length
4、如何表示一個數組的元素
數組名[下標]
下標的範圍:[0,長度-1]
5、遍歷數組
for(int i=0; i<數組的長度; i++){
System.out.println(數組名[i]);
}
*/
class Test07_ArrayDefineAndUse2{
public static void main(String[] args){
//例如:聲明一個數組,用來存儲26個大寫的英文字母
//(1)聲明數組
//char[] letters;
//(2)動態初始化
//數組名 = new 元素的數據類型[長度];
//①確定數組的長度
//letters = new char[26];
//可以把聲明與確定數組的長度合成一句
char[] letters = new char[26];
//(3)遍歷數組的元素
for(int i=0; i<letters.length; i++){
System.out.println((int)letters[i]);//發現默認值是\u0000
}
//②確定數組的元素的值
//letters[0] = 'A';
//letters[1] = 'B';
//...
for(int i=0; i<letters.length; i++){
//數組的元素 = 值;
letters[i] = (char)('A' + i);
}
System.out.println("-------------------------------");
//(4)遍歷數組的元素
for(int i=0; i<letters.length; i++){
System.out.println(letters[i]);//發現默認值是\u0000
}
}
}
2.3、數組的遍歷
for循環遍歷數組:
for(int i=0; i<數組名.lenght; i++){
//或賦值
數組名[i] = 值;
//或顯示
System.out.println(數組名[i]);
//或其他操作
//例如:判斷是否是偶數
if(數組名[i]%2==0){
//...
}
}
exercise
/*
1、數組的練習
用一個數組存儲本組學員的成績,並遍歷顯示
(1)其中學員的人數從鍵盤輸入
(2)學員的成績從鍵盤輸入
*/
class Test08_Exer4{
public static void main(String[] args){
/*
步驟:
1、先確定人數,從鍵盤輸入
2、聲明並創建數組,用來存儲成績
3、確定每一個成績:爲每一個元素賦值
4、遍歷顯示
*/
//1、先確定人數,從鍵盤輸入
java.util.Scanner input = new java.util.Scanner(System.in);
System.out.print("請輸入本組的人數:");
int count = input.nextInt();
//2、聲明並創建數組,用來存儲成績
//int[] scores = new int[長度];
int[] scores = new int[count];
//3、確定每一個成績:爲每一個元素賦值
for(int i=0; i<count; i++){
System.out.print("請輸入第"+ (i+1) + "個學員的成績:");
//爲元素賦值:爲誰賦值,就把誰寫在=的左邊
scores[i] = input.nextInt();//用鍵盤輸入的值爲元素賦值
}
//4、遍歷顯示
System.out.println("本組學員的成績如下:");
for(int i=0; i<scores.length; i++){
System.out.print(scores[i]+"\t");// \t 製表符
}
//請輸入本組的人數:5
//請輸入第1個學員的成績:1
//請輸入第2個學員的成績:2
//請輸入第3個學員的成績:3
//請輸入第4個學員的成績:4
//請輸入第5個學員的成績:5
//本組學員的成績如下:
//1 2 3 4 5
//Process finished with exit code 0
}
}
/*
2、數組的練習
用一個數組存儲26個英文字母的小寫形式,
並遍歷顯示
'a'->'A’
*/
class Test09_Exer5{
public static void main(String[] args){
//用一個數組存儲26個英文字母的小寫形式
//(1)聲明並創建數組
char[] letters = new char[26];
//(2)爲元素賦值,即把'a','b'等存儲到letters數組中
//因爲有規律,所以用循環賦值
for(int i=0; i<letters.length; i++){
letters[i] = (char)('a' + i);
}
//(3)顯示結果
//'a'->'A’
//->左邊就是元素的值,右邊是根據元素的值,算出來的
//'a'的編碼值是97,'A'編碼值爲65,差32
//'b'的編碼值是98,'B'編碼值爲66,差32
for(int i=0; i<letters.length; i++){
System.out.println(letters[i] +"->" + (char)(letters[i]-32));
}
//Result
//a->A
//b->B
//c->C
//d->D
//e->E
//f->F
//g->G
//h->H
//i->I
//j->J
//k->K
//l->L
//m->M
//n->N
//o->O
//p->P
//q->Q
//r->R
//s->S
//t->T
//u->U
//v->V
//w->W
//x->X
//y->Y
//z->Z
//
//Process finished with exit code 0
}
}
2.4、 數組的內存分析
元素是基本數據類型的一維數組內存分析:
int[] arr = {1,2,3,4,5};
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hhNvIxNb-1589129384818)(imgs/1558400311779.png)]
int[] arr = new int[5];
for(int i=0; i<arr.length; i++){
arr[i] = i+1;
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-07wK7g08-1589129384827)(imgs/1558400323314.png)]
new完有默認值的 int爲0,再賦值。
棧 堆
面向對象來了 複習複習。
不斷迭代的,我的筆記也要迭代,一路copy下來。
/*
數組的存儲:
1、數組下標爲什麼從0開始?
下標表示的是這個元素的位置距離首地址的偏移量
2、數組名中存儲的是什麼
數組名中存儲的是數組在堆中一整塊區域的首地址
3、數組的元素如何存儲
在堆中,依次連續的存儲的
說明:
數組名,其實也是變量。
回憶:
變量的聲明和初始化
數據類型 變量名 = 變量值;
現在:
int[] array = {1,3,5,7,9};
其中的 int[]也是一種數據類型,數組類型,它是一種引用數據類型
引用,表示引用一個“對象”,引用堆中的一塊內存
Java程序是在JVM中運行,JVM中的內存最最主要的兩塊區域:棧和堆
其中的棧就是存儲我們的局部變量(現在見到的變量都是局部變量),
堆中存儲的是對象
*/
class Test06_ArraySaveInMemory{
public static void main(String[] args){
int[] array = new int[]{1,3,5,7,9};
//int[] array = {1,3,5,7,9};
System.out.println(array);//打印數組名
//結果:[I@1b6d3586 不同的計算機不同時候運行都不一樣的
//這個值是,數組對象的類型@對象的hashCode編碼值
//其中[I,表示int[]類型
//15db9742是這個數組對象的hashCode編碼值,類似於每個人都有一個身份證號
System.out.println(System.identityHashCode(array));
//460141958
}
}
3、 數組的相關算法
3.1、 數組找最值
1、數組中找最值
思路:
(1)先假設第一個元素最大/最小
(2)然後用max/min與後面的元素一一比較
示例代碼:
int[] arr = {4,5,6,1,9};
//找最大值
int max = arr[0];
for(int i=1; i<arr.length; i++){
if(arr[i] > max){
max = arr[i];
}
}
假設第一個元素max/min,不斷比較,交換。
2、數組中找最值及其下標
情況一:找最值及其第一次出現的下標
思路:
(1)先假設第一個元素最大/最小
(2)然後用max/min與後面的元素一一比較
示例代碼:
int[] arr = {4,5,6,1,9};
//找最大值
int max = arr[0];
int index = 0;
for(int i=1; i<arr.length; i++){
if(arr[i] > max){
max = arr[i];
index = i;
}
}
或
int[] arr = {4,5,6,1,9};
//找最大值
int maxIndex = 0;
for(int i=1; i<arr.length; i++){
if(arr[i] > arr[maxIndex]){
maxIndex = i;
}
}
System.out.println("最大值:" + arr[maxIndex]);
情況二:找最值及其所有最值的下標(即可能最大值重複)
思路:
(1)先找最大值
①假設第一個元素最大
②用max與後面的元素一一比較
(2)遍歷數組,看哪些元素和最大值是一樣的
示例代碼:
int[] arr = {4,5,6,1,9};
//找最大值
int max = arr[0];
for(int i=1; i<arr.length; i++){
if(arr[i] > max){
max = arr[i];
}
}
//遍歷數組,看哪些元素和最大值是一樣的
for(int i=0; i<arr.length; i++){
if(max == arr[i]){
System.out.print(i+"\t");
}
}
3.2、數組統計:求總和、均值、統計偶數個數等
思路:遍歷數組,挨個的累加,判斷每一個元素
示例代碼:
int[] arr = {4,5,6,1,9};
//求總和、均值
int sum = 0;//因爲0加上任何數都不影響結果
for(int i=0; i<arr.length; i++){
sum += arr[i];
}
double avg = (double)sum/arr.length;
示例代碼2:
int[] arr = {4,5,6,1,9};
//求總乘積
long result = 1;//因爲1乘以任何數都不影響結果
for(int i=0; i<arr.length; i++){
result *= arr[i];
}
示例代碼3:
int[] arr = {4,5,6,1,9};
//統計偶數個數
int even = 0;
for(int i=0; i<arr.length; i++){
if(arr[i]%2==0){
even++;
}
}
3.3、 反轉
方法有兩種:
1、藉助一個新數組
2、首尾對應位置交換
第一種方式示例代碼:
int[] arr = {1,2,3,4,5,6,7,8,9};
//(1)先創建一個新數組
int[] newArr = new int[arr.length];
//(2)複製元素
int len = arr.length;
for(int i=0; i<newArr.length; i++){
newArr[i] = arr[len -1 - i];
}
//(3)捨棄舊的,讓arr指向新數組
arr = newArr;//這裏把新數組的首地址賦值給了arr
//(4)遍歷顯示
for(int i=0; i<arr.length; i++){
System.out.println(arr[i]);
}
第二種方式示例代碼:
int[] arr = {1,2,3,4,5,6,7,8,9};
//(1)計算要交換的次數: 次數 = arr.length/2
//(2)首尾交換
for(int i=0; i<arr.length/2; i++){//循環的次數就是交換的次數
//首 與 尾交換
int temp = arr[i];
arr[i] = arr[arr.length-1-i];
arr[arr.length-1-i] = temp;
}
//(3)遍歷顯示
for(int i=0; i<arr.length; i++){
System.out.println(arr[i]);
}
3.4、 複製
應用場景:
1、擴容
2、備份
3、截取
示例代碼:擴容
int[] arr = {1,2,3,4,5,6,7,8,9};
//如果要把arr數組擴容,增加1個位置
//(1)先創建一個新數組,它的長度 = 舊數組的長度+1
int[] newArr = new int[arr.length + 1];
//(2)複製元素
//注意:i<arr.length 因位arr比newArr短,避免下標越界
for(int i=0; i<arr.length; i++){
newArr[i] = arr[i];
}
//(3)把新元素添加到newArr的最後
newArr[newArr.length-1] = 新值;
//(4)如果下面繼續使用arr,可以讓arr指向新數組
arr = newArr;
//(4)遍歷顯示
for(int i=0; i<arr.length; i++){
System.out.println(arr[i]);
}
示例代碼:備份
int[] arr = {1,2,3,4,5,6,7,8,9};
//1、創建一個長度和原來的數組一樣的新數組
int[] newArr = new int[arr.length];
//2、複製元素
for(int i=0; i<arr.length; i++){
newArr[i] = arr[i];
}
//3、遍歷顯示
for(int i=0; i<arr.length; i++){
System.out.println(arr[i]);
}
示例代碼:截取
int[] arr = {1,2,3,4,5,6,7,8,9};
int start = 2;
int end = 5;
//1、創建一個新數組,新數組的長度 = end-start + 1;
int[] newArr = new int[end-start+1];
//2、賦值元素
for(int i=0; i<newArr.length; i++){
newArr[i] = arr[start + i];
}
//3、遍歷顯示
for(int i=0; i<newArr.length; i++){
System.out.println(newArr[i]);
}