陣列
學習目標:
1. jvm記憶體圖入門
2. 一維陣列的使用
3. 二維陣列的使用
4. 陣列的記憶體結構
5. 陣列中常見演算法
6. 陣列中常見的例外
一、JVM記憶體圖入門
java程式運行在jvm上,jvm記憶體主要分為五塊,結構如下:
每塊記憶體負責的職責如下:
- Java虛擬機堆疊(Java Virtual Machine Stacks):描述的是Java方法執行的記憶體模型:每個方法在執行的同時都會創建一個堆疊幀(Stack Frame),堆疊幀中存盤著區域變數表、運算元堆疊、動態鏈接、方法出口等資訊,每一個方法從呼叫直至執行完成的程序,會對應一個堆疊幀在虛擬機堆疊中入堆疊到出堆疊的程序,與程式計數器一樣,Java虛擬機堆疊也是執行緒私有的,
區域變數和參考地址都是在堆疊記憶體中,
-
堆:此記憶體區域的唯一目的就是存放物件實體,幾乎所有的物件實體都在這里分配記憶體,這一點在Java虛擬機規范中的描述是:所有的物件實體以及陣列都要在堆上分配,
-
方法區:用于存盤已被虛擬機加載的類資訊、常量、靜態變數、即時編譯器編譯后的代碼等資料,方法區存放的資料只有一份
-
本地方法堆疊(Native Method Stack):與Java虛擬機堆疊作用很相似,它們的區別在于虛擬機堆疊為虛擬機執行Java方法(即位元組碼)服務,而本地方法堆疊則為虛擬機使用到的Native方法服務,例如呼叫本地c/c++的方法,
-
程式計數器:程式計數器是記錄當前執行緒所執行的指令行數,
二、陣列的概述
2.1 為什么需要陣列
為什么要有陣列?在開發中,我們常常需要存取很多相同型別的資料,用變數的方式需要定義很多變數,不方便管理,所以引入陣列的概念,一次存取多個相同型別的資料,陣列有兩個一定,一個型別一定,一個是大小一定,
2.2 陣列的基本概念
陣列中存在著一些重要的概念,如下所示:
- 陣列名:陣列的名稱,陣列記憶體的首地址
- 下標名(索引):陣列元素的序號索引,從0開始
- 元素:陣列中存放的內容
- 長度 :陣列的長度
三、一維陣列的使用
3.1 陣列的定義
一維陣列的定義語法如下:
示例:
/**
* 陣列定義
*/
public class ArrayDemo1 {
public static void main(String[] args) {
//定義陣列
int[] arr1;
String [] arr2;
}
}
3.2 陣列的初始化
陣列動態初始化語法:
示例:
/**
* 陣列定義,以及動態初始化
*/
public class ArrayDemo1 {
public static void main(String[] args) {
//定義陣列
int[] arr1;
//陣列動態初始化
arr1 = new int[4];
arr1[0] = 10;
arr1[1] = 20;
arr1[2] = 30;
arr1[3] = 40;
//取值
System.out.println(arr1[0]);
System.out.println(arr1[1]);
System.out.println(arr1[2]);
System.out.println(arr1[3]);
}
}
陣列靜態初始化語法:
示例:
/*
陣列的定義與靜態初始化
*/
public class ArrayDemo2 {
public static void main(String[] args) {
//陣列的宣告
// String[] arr = new String[]{"喬峰","段譽","楊過"};
//簡寫
String[] arr = {"喬峰","段譽","楊過"};
//取值
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
}
}
3.3 陣列元素的參考
參考陣列元素內容需要注意以下幾點:
- 定義并用運算子new為之分配空間后,才可以參考陣列中的每個元素;
- 陣列元素的參考方式:陣列名[陣列元素下標]
- 陣列元素下標可以是整型常量或整型運算式,如a[3] , b[i] , c[6*i];
- 陣列元素下標從0開始;長度為n的陣列合法下標取值范圍: 0 —>n-1;如int a[]=new int[3]; 可參考的陣列元素為a[0]、a[1]、a[2]
- 每個陣列都有一個屬性length指明它的長度,例如:a.length 指明陣列a的長 度(元素個數) ,陣列一旦初始化,其長度是不可變的
示例1:陣列元素的參考
/**
* 陣列元素的參考
*/
public class ArrayDemo3 {
public static void main(String[] args) {
//陣列的定義
int[] arr = {1,3,5,7,9};
//查看陣列的長度
System.out.println(arr.length);
// 查看陣列內容
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println(arr[4]);
// 陣列下標超過最大下標會越界,報例外ArrayIndexOutOfBoundsException
System.out.println(arr[5]);
}
}
示例2:陣列的回圈賦值與取值
/**
* 陣列的回圈賦值與取值
*/
public class ArrayDemo4 {
public static void main(String[] args) {
//定義陣列
int[] arr = new int[5];
//回圈賦值
for (int i = 0; i < arr.length; i++) {
arr[i] = i*5;
}
//回圈取值
for (int i = 0; i < arr.length ; i++) {
System.out.println(arr[i]);
}
}
}
3.4 陣列的注意事項
陣列在使用程序中需要注意以下幾點:
- 陣列本身是參考資料型別,而陣列中的元素可以是任何資料型別,包括基本資料型別和參考資料型別,
- 創建陣列物件會在記憶體中開辟一整塊連續的空間,而陣列名中參考的是這塊連續空間的首地址,
- 陣列的長度一旦確定,就不能修改,
- 陣列的分類:
- 按照維度:一維陣列、二維陣列、三維陣列、…
- 按照元素的資料型別分:基本資料型別元素的陣列、參考資料型別元素的陣列(即物件陣列)
3.5 forEach的應用
forEach可以遍歷陣列或集合容器中的資料,語法如下:
示例:
/**
* forEach遍歷
*/
public class ArrayDemo5 {
public static void main(String[] args) {
//陣列定義
int[] arr = {1,3,5,7,9};
//陣列遍歷
for(int num : arr){
System.out.println(num);
}
}
}
3.6 陣列元素默認值
當陣列元素沒有賦值時,是存在默認值的,默認值如下:
3.7 一維陣列記憶體圖
3.8 小結
- 陣列的基本使用
- 資料型別可以是基本型別或參考型別
- 陣列型別固定長度不變
- 陣列默認值
- 陣列的記憶體圖
四、一維陣列練習題
4.1 陣列賦值練習
將班級所有同學名字錄入到一個一維陣列中 ,
參考答案:
/**
* 將班級所有同學名字錄入到一個一維陣列中
*/
public class ArrayTest1 {
public static void main(String[] args) {
//1.創建大小為5的String型別陣列
String[] names = new String[5];
//2.創建掃描儀物件
Scanner input = new Scanner(System.in);
for(int i=0;i<names.length;i++) {
//3.提示資訊
System.out.println("請輸入第"+(i+1)+"個同學名字");
//4.接收客戶的輸入資訊
String name = input.nextLine();
//5.將名字存入陣列中
names[i] = name;
}
System.out.println("學生資訊如下----------");
for(int i=0;i<names.length;i++) {
System.out.println(names[i]);
}
}
}
4.2 求陣列值練習
已知一個一維陣列如下int[] arr = {1,3,11,5,7,9};求出所有元素的最大值,最小值,和值,平均值,并輸出出來,
參考答案:
/**
* 已知一個一維陣列如下int[] arr = {1,3,11,5,7,9};求出所有元素的最大值,最小值,和值,平均值,并輸出出來,
*/
public class ArrayTest2 {
public static void main(String[] args) {
//定義陣列
int[] arr = {1,3,11,5,7,9};
//假設0下標是最大值 0下標是最小值
int max = arr[0];
int min = arr[0];
int sum = 0;
int avg = 0;
//2.判斷最大值和最小值
for(int i=0;i<arr.length;i++) {
if(max<arr[i]) {
max = arr[i];
}
if(min>arr[i]) {
min = arr[i];
}
sum+=arr[i];
}
avg = sum/arr.length;
System.out.println("最大值"+max);
System.out.println("最小值"+min);
System.out.println("和是"+sum);
System.out.println("平均值是"+avg);
}
}
4.3 陣列的復制
已知陣列int[] arr1 = {1,3,5,7,9} , int[] arr2; 將陣列arr1的內容復制到陣列arr2中
參考答案:
/**
* 已知陣列int[] arr1 = {1,3,5,7,9} , int[] arr2; 將陣列arr1的內容復制到陣列arr2中
*/
public class ArrayTest3 {
public static void main(String[] args) {
//1.定義陣列
int[] arr1,arr2;
//2.初始化
arr1 = new int[]{1,3,5,7,9};
//3.列印陣列arr1
for(int i=0;i<arr1.length;i++) {
System.out.println(arr1[i]);
}
//4.陣列復制操作
arr2 = new int[arr1.length];
for(int i=0;i<arr1.length;i++) {
arr2[i] = arr1[i];
}
}
}
注意:切不可 arr2 = arr1 這不是復制陣列內容,這是復制陣列記憶體地址;arr2和arr1會指向同一塊堆記憶體空間,改變arr2的同時也會改變arr1,改變arr1的同時也會改變arr2
4.4 陣列的反轉
已知一個陣列如下String[] arr = new String[]{"AA","BB","CC","DD","EE"};,反轉arr陣列得到如下結果String[] arr = new String[]{"EE","DD","CC","BB","AA"};
參考答案:
/**
* 已知一個陣列如下String[] arr = new String[]{"AA","BB","CC","DD","EE"};,
* 反轉arr陣列得到如下結果String[] arr = new String[]{"EE","DD","CC","BB","AA"};
*/
public class ArrayTest4 {
public static void main(String[] args) {
String[] arr = new String[]{"AA","BB","CC","DD","EE"};
for(int i=0;i<arr.length/2;i++) {
String str = arr[i];
arr[i] = arr[arr.length-i-1];
arr[arr.length-i-1] = str;
}
for(int i=0;i<arr.length;i++) {
System.out.println(arr[i]);
}
}
}
五、二維陣列的使用
如果說可以把一維陣列當成幾何中的線性圖形, 那么二維陣列就相當于是一個表格,就像下面圖一樣:
對于二維陣列的理解,我們可以理解為一維陣列的陣列,既陣列0下標是一個一維陣列,1下標又是一個一維陣列陣列...,
5.1 二維陣列的動態初始化
二維陣列存在兩種定義方式,第一種定義方式如下:
int[][]arr = new int[4][3]; 定義了名為arr的二維陣列,二維陣列中有4個一維陣列 每一個一維陣列中有3個元素- 一維陣列分別為arr[0], arr[1], arr[2] ,arr[3]
- 給第一個一維陣列0腳標位賦值為1寫法是:arr
[0][0]= 1; - arr 陣列的長度 arr.length;
- arr[0].length 代表arr陣列的0下標一維陣列的長度,
示例:
/**
* 二維陣列動態初始化1
*/
public class ArrayDemo7 {
public static void main(String[] args) {
//1.動態定義二維陣列方式1
/*兩種理解方式 y x
* 方式1 圖形化理解 4 行 3 列 二維陣列 int[][] arr = new int[4][3];
* 方式2 有 4 個 一維陣列 每個一維陣列可以存放3個數
*/
int[][] arr = new int[4][3];
//2.獲得 4 個一維陣列 arr[0] arr[1] arr[2] arr[3]
//列印 第0個陣列
System.out.print(arr[0][0]);
System.out.print(arr[0][1]);
System.out.println(arr[0][2]);
//列印 第1個陣列
System.out.print(arr[1][0]);
System.out.print(arr[1][1]);
System.out.println(arr[1][2]);
//列印 第2個陣列
System.out.print(arr[2][0]);
System.out.print(arr[2][1]);
System.out.println(arr[2][2]);
//列印 第3個陣列
System.out.print(arr[3][0]);
System.out.print(arr[3][1]);
System.out.println(arr[3][2]);
//3.查看二維陣列長度
System.out.println(arr.length);
//4. 查看二維陣列0下標長度
System.out.println(arr[0].length);
//5. 查看二維陣列1標長度
System.out.println(arr[1].length);
//6. 查看二維陣列2下標長度
System.out.println(arr[2].length);
//6. 查看二維陣列3下標長度
System.out.println(arr[3].length);
}
}
第二種定義方式如下:
int[][] arr = new int[3][]; 二維陣列中有3個一維陣列, 每個一維陣列都是默認初始化值null (注意:區別于格式1)- 可以對這個三個一維陣列分別進行初始化 arr[0] = new int[3]; arr[1] = new int[2]; arr[2] = new int[1];
注: int[][]arr = new int[][3]; 這種寫法是錯誤的
示例:
public class ArrayDemo8 {
public static void main(String[] args) {
//1.動態初始化2
/**
* 圖形化理解 定義 4行 圖形 幾列待定
* 定義 4 個 一維陣列 一維陣列內容 沒有初始化
*/
int[][] arr = new int[4][];
//2.定義arr[0] 一維數
arr[0] = new int[1];
//3.定義arr[1] 一維數
arr[1] = new int[2];
//4.定義arr[2] 一維數
arr[2] = new int[3];
//5.定義arr[3] 一維數
arr[3] = new int[4];
//6.查看 陣列長度
System.out.println(arr.length);
//7.查看0下標陣列長度
System.out.println(arr[0].length);
//8.查看1下標陣列長度
System.out.println(arr[1].length);
//9.查看2下標陣列長度
System.out.println(arr[2].length);
//10.查看3下標陣列長度
System.out.println(arr[3].length);
}
}
5.2 二維陣列的靜態初始化
int[][] arr = new int[][]{{1},{1,2},{1,2,3}}; 定義一個名稱為arr的二維陣列,二維陣列中有三個一維陣列
每一個一維陣列中具體元素也都已初始化 第一個一維陣列 arr[0] = {1}; 第二個一維陣列 arr[1] = {1,2}; 第三個一維陣列 arr[2] = {1,2,3};
以上代碼也可以簡寫為:int[][] arr = {{1},{1,2},{1,2,3}};
示例:
public class ArrayDemo9 {
public static void main(String[] args) {
//1.二維陣列靜態初始化
int[][] arr = new int[][] {
{1,1,1},
{2,2,2},
{3,3,3}
};
//2.簡化
int[][] arr2 = {
{1},
{2,2},
{3,3,3}
};
}
}
5.3 二維陣列的遍歷
二維陣列回圈賦值與遍歷程序如下
public class ArrayDemo10 {
public static void main(String[] args) {
//1.矩形
int[][] arr1 = new int[4][3];
//2.回圈賦值
for(int y=0;y<arr1.length;y++) {
for(int x=0;x<arr1[y].length;x++) {
arr1[y][x] = 1;
}
}
//3.回圈遍歷
for(int y=0;y<arr1.length;y++) {
for(int x=0;x<arr1[y].length;x++) {
System.out.print(arr1[y][x]+"\t");
}
System.out.println();
}
//2.直角三角形練習
String[][] arr2 = new String[4][];
//3.回圈賦值
for(int y=0;y<arr2.length;y++) {
//4.定義一維陣列
arr2[y] = new String[y+1];
for(int x=0;x<arr2[y].length;x++) {
arr2[y][x] = "*";
}
}
//4.列印二維陣列
for(int y=0;y<arr2.length;y++) {
for(int x=0;x<arr2[y].length;x++) {
System.out.print(arr2[y][x]);
}
System.out.println();
}
}
}
5.4 小結
-
二維陣列的動態初始化
-
二維陣列的靜態初始化
-
二維陣列的遍歷
六、二維陣列練習題
6.1 楊輝三角
使用二維陣列列印一個10行的楊輝三角
參考答案:
public class ArrayDemo11 {
public static void main(String[] args) {
//1.定義楊輝三角二維陣列
int[][] arr = new int[10][];
//2.回圈初始化 二維陣列
for(int y=0;y<arr.length;y++) {
arr[y] = new int[y+1];
//3.給每一行的第一個值和最后一個值賦值為 1
arr[y][0] = arr[y][y] = 1;
//4.給其他位置賦值
//if(y>1) {
for(int x=1;x<arr[y].length-1;x++) {
arr[y][x] = arr[y-1][x-1]+arr[y-1][x];
}
//}
}
//3.遍歷
for(int y=0;y<arr.length;y++) {
for(int x=0;x<arr[y].length;x++) {
System.out.print(arr[y][x]+"\t");
}
System.out.println();
}
}
}
七、陣列中常見演算法
7.1 二分查找演算法
已知陣列int[] arr = {1,3,5,7,9,11,13};通過二分查找法查找陣列中是否包含元素3,如果包含,元素3的下標是多少?注意(只有排好序的陣列才能使用二分查找法)
分析程序如下:
另一種情況,當查找元素大于中間元素middle程序如下,這里以查找13為例
參考代碼:
/**
* 陣列元素二分查找法,前提:已排序的陣列
*/
public class BinarySearchArray {
public static void main(String[] args) {
//定義陣列
int[] arr = {1,3,5,7,9,11,13};
// 定義查找目標數
int target = 3;
//開始下標
int head = 0;
//結束下標
int end = arr.length-1;
//標記是否找到目標元素
boolean tag = true;
//二分查找
while(head<=end){
int middle = (head+end)/2;
if(arr[middle]==target){
System.out.println("查找到元素:"+target+",下標:"+middle);
tag = false;
break;
}else if(arr[middle]>target){
end=middle-1;
} else {
head=middle+1;
}
}
if(tag){
System.out.println("沒有找到目標元素"+target);
}
}
}
7.2 陣列的排序介紹(其余排序,由于演算法過于復雜,后期統一講)
排序:是計算機程式設計中的一項重要操作,是指對陣列或集合中的元素進行按照大小或字母排序,
排序的演算法有很多很多種,這里以冒泡排序、選擇排序、插入排序為例進行講解,
7.3 冒泡排序
冒泡排序的設計思想:從0下標開始比較相鄰元素,通過交換下標元素位置,把大的元素放后面,小的元素放前面, 比較完一輪完成最后一個元素是最大的,以此類推,經過n輪比較完成排序的程序,
代碼實作分析
- 一共比較幾輪?
- 每輪比較幾次?
參考答案
/**
* 冒泡排序
*/
public class SortDemo1 {
public static void main(String[] args) {
//定義陣列
int[] arr = {1,11,9,3,7,5};
//排序
for(int i=0;i<arr.length-1;i++){ //如果有6個數,比較5輪就可以了,剩下一個一定是最小的
// 因為是j和j+1比較所以j<arr.length-1,又因為每比較一次,就少比較一個數,
// 所以j<arr.length-1-i;
for(int j=0;j<arr.length-1-i;j++){
// 比較相鄰元素,交換相鄰下標位置
if(arr[j]>arr[j+1]){
int t = arr[j];
arr[j] = arr[j+1];
arr[j+1] = t;
}
}
}
//列印陣列
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}
7.4 選擇排序
選擇排序的思路是:
- 將0下標和后面所有元素比,如果0下標不是最小元素,就交換位置,比較完一輪0下標就是最小的元素
- 以此類推將1下標元素和后面所有元素比較,如果1下標不是最小元素,就交換位置,比較完一輪1下標就第二小的元素
- 依此類推,完成整個陣列的排序
代碼實作分析
- 一共比較幾輪?
- 每輪比較幾次?
參考答案:
/**
* 選擇排序
*/
public class SortDemo2 {
public static void main(String[] args) {
//定義陣列
int[] arr = {1,11,9,3,7,5};
//選擇排序
for(int i=0;i<arr.length-1;i++){ //如果6個數,比較5輪即可,剩下最后一個一定是最大的
//讓0下標i和后面所有下標比較;所以開始是i+1 結束到最大下標
for(int j=i+1;j<arr.length;j++){
if(arr[i]>arr[j]){
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
}
//列印陣列
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}
7.5 插入排序
插入排序的設計思路是:
- 從第一個元素開始,該元素可以認為已經被排序
- 取出下一個元素,在已經排序的元素序列中從后向前掃描
- 如果該元素(已排序)大于新元素,將該元素移到下一位置
- 重復步驟3,直到找到已排序的元素小于或者等于新元素的位置
- 將新元素插入到該位置后
- 重復步驟2~5
參考答案:
/**
* 插入排序
*/
public class SortDemo3 {
public static void main(String[] args) {
//定義陣列
int[] arr = {1,11,9,3,7,5};
//插入排序
for(int index = 1;index<arr.length;index++){
int t = arr[index];
int leftIndex = index-1;
while(leftIndex>=0 && arr[leftIndex]>t){
arr[leftIndex+1] = arr[leftIndex];
leftIndex--;
}
arr[leftIndex+1] = t;
}
//列印陣列
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}
7.6 小結
-
二分查找
-
冒泡排序
-
選擇排序
-
插入排序
八、陣列中常見的例外
陣列中的常見例外:
- 陣列角標越界的例外:ArrayIndexOutOfBoundsExcetion
- 空指標例外:NullPointerException
九、總結
-
一維陣列的使用
-
二維陣列的使用
-
一維陣列的常見演算法:查找和排序,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/499714.html
標籤:Java
