Java一維二維數(shù)組的使用方法詳解(Arrays類(lèi)方法)
一:數(shù)組的概念以及定義,初始化
1.1:數(shù)組概念以及定義
數(shù)組概念:可以看成是 相同類(lèi)型元素的一個(gè)集合 。
數(shù)組定義:三種方法
T [] 數(shù)組名 = new T [ N ];例如:int[]arr = new arr[10];
T :表示數(shù)組中存放元素的類(lèi)型
T[]:表示數(shù)組的類(lèi)型
N :表示數(shù)組的長(zhǎng)度
例如:
int [] array1 = new int [ 10 ]; // 創(chuàng)建一個(gè)可以容納 10 個(gè) int 類(lèi)型元素的數(shù)組 double [] array2 = new double [ 5 ]; // 創(chuàng)建一個(gè)可以容納 5 個(gè) double 類(lèi)型元素的數(shù)組 String [] array3 = new String [ 3 ]; // 創(chuàng)建一個(gè)可以容納 3 個(gè)字符串元素的數(shù)組
1.2:數(shù)組的初始化主要有兩種:動(dòng)態(tài)初始化以及靜態(tài)初始化
1.靜態(tài)初始化和動(dòng)態(tài)初始化一步完成
數(shù)組動(dòng)態(tài)初始化:在創(chuàng)建數(shù)組時(shí),直接指定數(shù)組中元素的個(gè)數(shù)
int [] array = new int [ 10 ];這種初始化,這個(gè)arr數(shù)組里面的值都為0;
靜態(tài)初始化:在創(chuàng)建數(shù)組時(shí)不直接指定數(shù)據(jù)元素個(gè)數(shù),而直接將具體的數(shù)據(jù)內(nèi)容進(jìn)行指定
靜態(tài)初始化雖然沒(méi)有指定數(shù)組的長(zhǎng)度,編譯器在編譯時(shí)會(huì)根據(jù) {} 中元素個(gè)數(shù)來(lái)確定數(shù)組的長(zhǎng)度
語(yǔ)法格式: T[] 數(shù)組名稱(chēng) = {data1, data2, data3, ..., datan};
例如:
int [] array1 = new int []{ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }; double [] array2 = new double []{ 1.0 , 2.0 , 3.0 , 4.0 , 5.0 }; String [] array3 = new String []{ "hell" , "Java" , "!!!" };
靜態(tài)初始化可以省略可以省去后面的new int[];
直接就是 int [] array1 = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
但是這種初始化是嚴(yán)令禁止的: int [] array1 = new int [10]{ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };, 編譯器會(huì)報(bào)錯(cuò)誤
2.同時(shí)靜態(tài)初始化和動(dòng)態(tài)初始化也可以分為兩步:
int [] array1 ; array1 = new int [ 10 ]; int [] array2 ; array2 = new int []{ 10 , 20 , 30 }; // 注意省略格式不可以拆分, 否則編譯失敗 // int[] array3; // array3 = {1, 2, 3}; 這樣不可以,?。?!只能在定義的時(shí)候進(jìn)行賦值
1.如果沒(méi)有對(duì)數(shù)組進(jìn)行初始化,數(shù)組中元素有其默認(rèn)值:
2.如果數(shù)組中存儲(chǔ)元素類(lèi)型為引用類(lèi)型,默認(rèn)值為null
二:數(shù)組的使用:
1.1:數(shù)組的訪問(wèn):
數(shù)組下表訪問(wèn)不能越界:
int [] array = { 1 , 2 , 3 }; System . out . println ( array [ 3 ]); // 數(shù)組中只有 3 個(gè)元素,下標(biāo)一次為: 0 1 2 , array[3] 下標(biāo)越界
數(shù)組越界異常
1.2:數(shù)組遍歷
1.一般C中我們都是循環(huán)遍歷:但是java中注意:在數(shù)組中可以通過(guò) 數(shù)組對(duì)象.length 來(lái)獲取數(shù)組的長(zhǎng)度
int [] array = new int []{ 10 , 20 , 30 , 40 , 50 }; for ( int i = 0 ; i < array . length ; i ++ ){ System . out . println ( array [ i ]); }
2.java也可以使用for-each遍歷數(shù)組:
int [] array = { 1 , 2 , 3 }; for ( int x : array ) { System . out . println ( x ); }
2:數(shù)組是引用類(lèi)型
2.1:要了解數(shù)組首先,要了解引用到底是什么?
在java里 數(shù)據(jù)類(lèi)型分為兩大類(lèi):基本數(shù)據(jù)類(lèi)型(Primitive Types)和引用數(shù)據(jù)類(lèi)型(Reference Types)。引用數(shù)據(jù)類(lèi)型是相對(duì)于基本數(shù)據(jù)類(lèi)型而言的,它們不是直接在內(nèi)存中存儲(chǔ)數(shù)據(jù)值,而是存儲(chǔ)數(shù)據(jù)的引用(或者說(shuō)是指向數(shù)據(jù)的內(nèi)存地址)。
Java中的引用數(shù)據(jù)類(lèi)型主要包括以下幾類(lèi):
類(lèi),數(shù)組,枚舉,接口,注解
我們現(xiàn)在現(xiàn)在需要注意這兩項(xiàng):
類(lèi)(Class Types):類(lèi)是Java程序的基本構(gòu)建塊,用于創(chuàng)建對(duì)象。每個(gè)對(duì)象都是類(lèi)的一個(gè)實(shí)例,而類(lèi)本身就是一種引用數(shù)據(jù)類(lèi)型。你可以定義自己的類(lèi)來(lái)封裝數(shù)據(jù)和邏輯,Java標(biāo)準(zhǔn)庫(kù)中也提供了大量的類(lèi)供我們使用。
數(shù)組(Array Types):數(shù)組是一種特殊的引用類(lèi)型,用于存儲(chǔ)固定大小的同類(lèi)型元素。數(shù)組可以是基本數(shù)據(jù)類(lèi)型的數(shù)組,也可以是引用數(shù)據(jù)類(lèi)型的數(shù)組(比如對(duì)象數(shù)組或另一個(gè)數(shù)組的數(shù)組)。
2.2:初始JVM的內(nèi)存分布:
內(nèi)存是一段連續(xù)的存儲(chǔ)空間,主要用來(lái)存儲(chǔ)程序運(yùn)行時(shí)數(shù)據(jù)的。比如:
1. 程序運(yùn)行時(shí)代碼需要加載到內(nèi)存
2. 程序運(yùn)行產(chǎn)生的中間數(shù)據(jù)要存放在內(nèi)存
3. 程序中的常量也要保存
4. 有些數(shù)據(jù)可能需要長(zhǎng)時(shí)間存儲(chǔ),而有些數(shù)據(jù)當(dāng)方法運(yùn)行結(jié)束后就要被銷(xiāo)毀
如果對(duì)內(nèi)存中存儲(chǔ)的數(shù)據(jù)不加區(qū)分的隨意存儲(chǔ),那對(duì)內(nèi)存管理起來(lái)將會(huì)非常麻煩。比如:
因此 JVM 也對(duì)所使用的內(nèi)存按照功能的不同進(jìn)行了劃分:
- 程序計(jì)數(shù)器 (PC Register): 只是一個(gè)很小的空間, 保存下一條執(zhí)行的指令的地址
- 虛擬機(jī)棧(JVM Stack): 與方法調(diào)用相關(guān)的一些信息,每個(gè)方法在執(zhí)行時(shí),都會(huì)先創(chuàng)建一個(gè)棧幀,棧幀中包含 有:局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、返回地址以及其他的一些信息,保存的都是與方法執(zhí)行時(shí)相關(guān)的一 些信息。比如:局部變量。當(dāng)方法運(yùn)行結(jié)束后,棧幀就被銷(xiāo)毀了,即棧幀中保存的數(shù)據(jù)也被銷(xiāo)毀了。
- 本地方法棧(Native Method Stack): 本地方法棧與虛擬機(jī)棧的作用類(lèi)似. 只不過(guò)保存的內(nèi)容是Native方法的局 部變量. 在有些版本的 JVM 實(shí)現(xiàn)中(例如HotSpot), 本地方法棧和虛擬機(jī)棧是一起的
- 堆(Heap): JVM所管理的最大內(nèi)存區(qū)域. 使用 new 創(chuàng)建的對(duì)象都是在堆上保存 (例如前面的 new int[]{1, 2, 3} ),
- 堆是隨著程序開(kāi)始運(yùn)行時(shí)而創(chuàng)建,隨著程序的退出而銷(xiāo)毀,堆中的數(shù)據(jù)只要還有在使用,就不會(huì)被銷(xiāo)毀。
- 方法區(qū)(Method Area): 用于存儲(chǔ)已被虛擬機(jī)加載的類(lèi)信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù). 方法編譯出的的字節(jié)碼就是保存在這個(gè)區(qū)域
- 現(xiàn)在我們只簡(jiǎn)單關(guān)心堆 和 虛擬機(jī)棧這兩塊空間,后序JVM中還會(huì)更詳細(xì)介紹。
2.3基本類(lèi)型變量與引用類(lèi)型變量的區(qū)別
基本數(shù)據(jù)類(lèi)型創(chuàng)建的變量,稱(chēng)為基本變量,該變量空間中直接存放的是其所對(duì)應(yīng)的值;
引用數(shù)據(jù)類(lèi)型創(chuàng)建的變量,一般稱(chēng)為對(duì)象的引用,存儲(chǔ)的是對(duì)象所在空間的地址的變量。
從上圖可以看到, 引用變量并不直接存儲(chǔ)對(duì)象本身,可以簡(jiǎn)單理解成存儲(chǔ)的是對(duì)象在堆中空間的起始地址。通過(guò)該
地址,引用變量便可以去操作對(duì)象 。有點(diǎn)類(lèi)似 C 語(yǔ)言中的指針,但是 Java 中引用要比指針的操作更簡(jiǎn)單。
再看一個(gè)例子:
2.4:空指針:null
null 在 Java 中表示 " 空引用 " , 也就是一個(gè)不指向?qū)ο蟮囊?nbsp;.
int [] arr = null ; System . out . println ( arr [ 0 ]); // 執(zhí)行結(jié)果 Exception in thread "main" java . lang . NullPointerException at Test . main ( Test . java : 6 )
null 的作用類(lèi)似于 C 語(yǔ)言中的 NULL ( 空指針 ), 都是表示一個(gè)無(wú)效的內(nèi)存位置 . 因此不能對(duì)這個(gè)內(nèi)存進(jìn)行任何讀寫(xiě)操 作. 一旦嘗試讀寫(xiě) , 就會(huì)拋出 NullPointerException.
注意 : Java 中并沒(méi)有約定 null 和 0 號(hào)地址的內(nèi)存有任何關(guān)聯(lián)
3:數(shù)組應(yīng)用場(chǎng)景:
3.1:數(shù)組作為函數(shù)參數(shù):一張圖弄懂
總結(jié) : 所謂的 " 引用 " 本質(zhì)上只是存了一個(gè)地址(還不是真的內(nèi)存地址) . Java 將數(shù)組設(shè)定成引用類(lèi)型 , 這樣的話(huà)后續(xù)進(jìn)行數(shù)組參數(shù)傳參 ,
其實(shí)只是將數(shù)組的地址傳入到函數(shù)形參中. 這樣可以避免對(duì)整個(gè)數(shù)組的拷貝 ( 數(shù)組可能比較長(zhǎng) , 那么拷貝開(kāi)銷(xiāo)就會(huì)很大 ).
3.2:數(shù)組作為函數(shù)的返回值
public class Test { public static int[] func(){ int []array = new int[]{1,2,3,4,5}; return array; } 實(shí)話(huà)說(shuō)這個(gè)array數(shù)組是個(gè)臨時(shí)變量,在C里面func返回時(shí)會(huì)被銷(xiāo)毀,但是在java里面這個(gè)還是一直存在的就不會(huì)銷(xiāo)毀 public static void main(String[] args) { int[] ret = func(); for (int i = 0; i < ret.length; i++) { System.out.println(ret[i]); } } }
4:數(shù)組練習(xí):
4.1:數(shù)組轉(zhuǎn)化為字符串Arrays.toString
public static String myToString(int[] arr) { String ret = "["; for (int i = 0; i < arr.length; i++) { ret += arr[i]; if (i != arr.length - 1) { ret += ","; } else { ret += "]"; } } return ret; } public static void main(String[] args) { int[] arr = {1, 2, 3, 4}; String ret = myToString(arr); System.out.println(ret); } }
注意ret是String類(lèi)型,每次都是ret+=……,最后直接打印
但是 Arrays.toString這個(gè)方法直接幫我們數(shù)組轉(zhuǎn)化為字符串:
4.2:拷貝方法:Arrays.copyOf Arrays.copyOfRange
巧了,我們java里面已經(jīng)幫我們實(shí)現(xiàn)好了:Arrays.copyOf這個(gè)方法(這個(gè)方法里面的參數(shù)(換個(gè)類(lèi)型)還是有很多的,一起構(gòu)成了方法的重載)
public static void main(String[] args) { //Arrays.copyOf(),Arrays.copyOfRange() int[] arr = {1, 2, 3, 4}; int[] copy = Arrays.copyOf(arr, arr.length * 2); //并且這里我們還可以進(jìn)行兩倍的拷貝,因?yàn)檫@個(gè)數(shù)組沒(méi)有長(zhǎng)度嘛,不用考慮越界的問(wèn)題 System.out.println(Arrays.toString(copy)); <strong>還可以選擇拷貝:</strong> int[] copy2 = Arrays.copyOfRange(arr, 1, 2);但是這個(gè)是從arr數(shù)組內(nèi)部拷過(guò)來(lái)的 System.out.println(Arrays.toString(copy2)); }
這里大家可以發(fā)現(xiàn)打印的有12個(gè)因?yàn)槭荹1,13)左閉右開(kāi),,但是arr從1開(kāi)始里面只有3個(gè)數(shù),然后就只能copy3個(gè)數(shù)然后補(bǔ)0
那這些方法的源碼是怎么實(shí)現(xiàn)的呢:大家可以看我這張圖
但是源代碼實(shí)現(xiàn)的話(huà)又會(huì)有一些的的問(wèn)題:就不能拷貝上述的12個(gè)了
我們盡量還是用Arrays.copyOfRange這個(gè)方法
注意:
數(shù)組當(dāng)中存儲(chǔ)的是基本類(lèi)型數(shù)據(jù)時(shí),不論怎么拷貝基本都不會(huì)出現(xiàn)什么問(wèn)題,但如果存儲(chǔ)的是引用數(shù)據(jù)類(lèi) 型,拷貝時(shí)需要考慮深淺拷貝的問(wèn)題,關(guān)于深淺拷貝在后續(xù)詳細(xì)給大家介紹
4.3:二分查找以及排序方法:
二分查找:針對(duì) 有序數(shù)組 ,返回的值返回的是最后一次的位置left然后 -(left+1)
所以說(shuō)按下面這個(gè)數(shù)組,key每次都>10的話(huà),每次返回都是-9
這是我模仿源碼的方法寫(xiě)的
public class Test { public static void main(String[] args) { int []arr = {1,2,3,4,5,6,7,8,9}; int key =7; int ret = binarySearch(arr,arr.length,key); System.out.println(ret); } public static int binarySearch(int []arr,int sz,int key){ int left = 0; int right = sz-1; while(left < right){ int mid = (left +right)>>>1;//這個(gè)右移一位就很秒 if(arr[mid] < key){ left = mid + 1; } else if(arr[mid]>key){ right = mid -1; }else{ return mid; } } return -(left+1); } }
源碼:
但是如果不是有序地呢,我們可以自己實(shí)現(xiàn)一個(gè)冒泡排序 以及配合的找數(shù)字的,但是java里面已經(jīng)幫我們實(shí)現(xiàn)的有方法了——Arrays.sort
以及配合找數(shù)字的Arrays.binarySearch
不過(guò)返回的值就是拍完序之后的位置了,這個(gè)一定要注意?。?!
二分查找優(yōu)點(diǎn):針對(duì)一個(gè)長(zhǎng)度為 10000 個(gè)元素的數(shù)組查找 , 二分查找只需要循環(huán) 14 次就能完成查找 . 隨著數(shù)組元素個(gè)數(shù) 越多, 二分的優(yōu)勢(shì)就越大 .
4.4:填充方法以及比較方法:
填充也可以指定范圍:java 太妙啦?。?!
4.5:數(shù)組求平均值
代碼兩個(gè)注意點(diǎn)
1:首先使用 for -each遍歷數(shù)組時(shí),這里的X其實(shí)就是數(shù)組里面的值
2:最后求平均值一定要強(qiáng)轉(zhuǎn)成double 類(lèi)型
public static void main(String[] args) { int[] arr = {1,2,3,4,5,6}; System.out.println(avg(arr)); } public static double avg(int[] arr) { int sum = 0; for (int x : arr) { sum += x;//注意這個(gè) } return (double)sum / (double)arr.length;//注意 }
三:二維數(shù)組的使用
1.二維數(shù)組的4種定義方式
二維數(shù)組是特殊的一維數(shù)組
二維數(shù)組的定義方法:一般就是這三種
int [][] array = {{1,2,3},{4,5,6}}; int [][] array1 = new int[][]{{1,2,3},{4,5,6}}; int [][] array2 = new int[2][3];
但是二維數(shù)組還可以不指定列,只指定行(和C語(yǔ)言相反)(第四種)
int [][] array = new int[2][]; String ret = Arrays.toString(array); System.out.println(ret);
(這個(gè)時(shí)候就相當(dāng)于,只初始化了兩個(gè)值,array[0],array[1],他們兩個(gè)的值默認(rèn)都是null,(這個(gè)時(shí)候就完全可以看出來(lái)array(二維數(shù)組就是特殊的一維數(shù)組)))
然后我可以這樣給他賦值
int [][] array = new int[2][]; array[0] = new int[]{1,2,3}; array[1] = new int[]{1,2,3,4,5,6};
2.二維數(shù)組的遍歷:
我們上述描述過(guò)了一維數(shù)組(array)的長(zhǎng)度是array.length,我們現(xiàn)在又知道了二維數(shù)組又是特殊的一維數(shù)組(譬如上述的array[2][],那么它的長(zhǎng)度就是array.length,它經(jīng)過(guò)初始化之后array[1].length就是3)
那么我們有了上述的知識(shí)之后就可以寫(xiě)出下面的代碼
int [][] array = new int[][]{{1,2,3},{4,5,6}}; for (int i = 0; i < array.length; i++) { for (int j = 0; j < array[i].length; j++) { System.out.print(array[i][j]+" "); } System.out.println();// 打印一行換行 }
3.二維數(shù)組的打印
那我們這樣打印呢?
int [][] array = new int[][]{{1,2,3},{4,5,6}}; System.out.println(array[0]); System.out.println(array[1]);
打印的不是實(shí)際的地址是經(jīng)過(guò)修改的地址,實(shí)際上是
最后調(diào)用的是 toString方法
再看看接下來(lái)打印的是什么呢?
int [][] array = new int[][]{{1,2,3},{4,5,6}}; System.out.println(array[0]); System.out.println(array[1]); System.out.println("============="); System.out.println(Arrays.toString(array[0])); System.out.println(Arrays.toString(array[1])); System.out.println("============="); System.out.println(array[0].length); System.out.println(array[1].length); System.out.println("============="); System.out.println(array.length); System.out.println("=============");
這個(gè)呢?
int [][] array = new int[][]{{1,2,3},{4,5,6}}; System.out.println(Arrays.toString(array)); System.out.println(Arrays.deepToString(array));
上述
總結(jié)
到此這篇關(guān)于Java一維二維數(shù)組的使用方法的文章就介紹到這了,更多相關(guān)Java一維二維數(shù)組使用方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在SpringBoot框架中實(shí)現(xiàn)打印響應(yīng)的日志
這篇文章主要介紹了在SpringBoot框架中實(shí)現(xiàn)打印響應(yīng)的日志,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05Java Socket實(shí)現(xiàn)文件傳輸示例代碼
這篇文章主要介紹了Java Socket實(shí)現(xiàn)文件傳輸示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01Java訪問(wèn)修飾符public、private、protected及默認(rèn)訪問(wèn)權(quán)限詳解
這篇文章主要介紹了Java訪問(wèn)修飾符public、private、protected及默認(rèn)訪問(wèn)權(quán)限的相關(guān)資料,每種修飾符都有其特定的使用場(chǎng)景,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-01-01java.lang.OutOfMemoryError: Metaspace異常解決的方法
這篇文章主要介紹了java.lang.OutOfMemoryError: Metaspace異常解決的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03java項(xiàng)目中常用指標(biāo)UV?PV?QPS?TPS含義以及統(tǒng)計(jì)方法
文章介紹了現(xiàn)代Web應(yīng)用中性能監(jiān)控和分析的重要性,涵蓋了UV、PV、QPS、TPS等關(guān)鍵指標(biāo)的統(tǒng)計(jì)方法,并提供了示例代碼,同時(shí),文章還討論了性能優(yōu)化和瓶頸分析的策略,以及使用Grafana等可視化工具進(jìn)行監(jiān)控與告警的重要性2025-01-01使用Mybatis Generator結(jié)合Ant腳本快速自動(dòng)生成Model、Mapper等文件的方法
這篇文章主要介紹了使用Mybatis Generator結(jié)合Ant腳本快速自動(dòng)生成Model、Mapper等文件的方法的相關(guān)資料,需要的朋友可以參考下2016-06-06