- 好好學(xué)Java:從零基礎(chǔ)到項(xiàng)目實(shí)戰(zhàn)
- 歐陽燊
- 2749字
- 2022-07-27 19:14:58
3.3.4 數(shù)組工具Arrays
數(shù)組作為一種組合形式的數(shù)據(jù)類型,必然要求提供一些處理數(shù)組的簡便辦法,包括數(shù)組比較、數(shù)組復(fù)制、數(shù)組排序等。為此,Java專門設(shè)計(jì)了Arrays工具,該工具包含幾個(gè)常用方法,方便程序員加工數(shù)組。Arrays工具的常見方法簡述如下:
- Arrays.equals(a1,a2); 判斷a1和a2兩個(gè)數(shù)組是否相等,也就是每個(gè)元素是否都相等。
- Arrays.fill(a,val); 往數(shù)組a中填入指定的數(shù)值val。
- dest=Arrays.copyOf(src,newLength); 把數(shù)組src的內(nèi)容賦值給數(shù)組dest,且dest的長度為newLength。
- Arrays.sort(a); 對數(shù)組a的內(nèi)部元素排序,默認(rèn)按照升序排序。
下面詳細(xì)介紹以上4個(gè)數(shù)組處理方法的使用。
1.Arrays.equals方法
前面說過,雙等號“==”可用來判斷兩個(gè)變量的數(shù)值是否相等,但只適合基本變量類型之間的比較,例如比較兩個(gè)整型變量是否相等、兩個(gè)雙精度數(shù)是否相等、兩個(gè)布爾變量是否相等。若兩個(gè)數(shù)組變量通過“==”判斷相等與否,則比較的是這兩個(gè)數(shù)組是否為同一個(gè)數(shù)組,而不是比較兩個(gè)數(shù)組的所有元素是否都相等。要想判斷兩個(gè)數(shù)組內(nèi)部的每個(gè)元素是否一一相等,就必須通過Arrays工具的equals方法來辨別。equals方法返回true表示兩個(gè)數(shù)組的所有元素都相等,返回false表示兩個(gè)數(shù)組至少有一個(gè)元素不相等。
2.Arrays.fill方法
在聲明數(shù)組變量的時(shí)候,經(jīng)常需要對它初始化賦值,比如書店進(jìn)了10本書,每本書的售價(jià)都是99元,那么按照常規(guī)寫法只能書寫10遍99,就像下面的代碼這樣:
// 構(gòu)造一個(gè)包含10個(gè)99的數(shù)組變量 int[] prices={99, 99, 99, 99, 99, 99, 99, 99, 99, 99};
顯然輸入重復(fù)的數(shù)字是個(gè)負(fù)擔(dān),尤其重復(fù)數(shù)量很多的時(shí)候更甚。現(xiàn)在利用Arrays的fill方法,只需一行代碼即可對該數(shù)組的所有元素都填上相同的數(shù)值,于是數(shù)組的初始賦值代碼便優(yōu)化為下面這樣(完整代碼見本章源碼的src\com\control\array\ArrayFill.java):
int[] prices=new int[10]; // 聲明一個(gè)整型數(shù)組,數(shù)組大小為10 Arrays.fill(prices, 99); // 給整型數(shù)組的每個(gè)元素全部填寫99 for (int price : prices) { // 循環(huán)遍歷并打印整型數(shù)組的所有元素?cái)?shù)值 System.out.println("price="+price); }
3.Arrays.copyOf方法
把一個(gè)數(shù)組變量賦值給另一個(gè)數(shù)組變量,似乎可以用等號直接賦值,這在一般情況下沒有問題,但如果賦值之后修改了原數(shù)組的某個(gè)元素,就會出現(xiàn)問題了。譬如以下的演示代碼,先把數(shù)組變量pricesOrigin賦值給pricesAssign,接著修改原數(shù)組pricesOrigin的元素值,再打印新數(shù)組pricesAssign的所有元素(完整代碼見本章源碼的src\com\control\array\ArrayCopy.java):
int[] pricesOrigin={99, 99, 99, 99, 99};// 聲明一個(gè)整型數(shù)組,數(shù)組大小為5,且5個(gè)元素全為99 // 復(fù)制數(shù)組的第一個(gè)辦法:利用等號直接賦值。新數(shù)組只是原數(shù)組的別名 int[] pricesAssign=pricesOrigin; pricesOrigin[1]=80; for (int price : pricesAssign) { // 循環(huán)遍歷并打印整型數(shù)組的所有元素?cái)?shù)值 System.out.println("assign price="+price); }
運(yùn)行以上的演示代碼,完整的日志輸出如下:
assign price=99
assign price=80
assign price=99
assign price=99
assign price=99
沒想到打印出來的第二個(gè)數(shù)組元素竟然變了,可是演示代碼明明只改了原數(shù)組pricesOrigin,并未修改新數(shù)組pricesAssign?讓測試程序錯(cuò)亂的緣故是數(shù)組之間的等號賦值相當(dāng)于給數(shù)組起一個(gè)別名,并非從頭到尾完整復(fù)制一個(gè)新數(shù)組出來。既然只是起了別名,那么實(shí)際上還是原名稱所指的數(shù)組,無非是該數(shù)組有兩個(gè)名字罷了。
顯然這種情況不是程序員期望的結(jié)果,程序員的本意是復(fù)制另外的數(shù)組,新數(shù)組不再與原數(shù)組有任何關(guān)聯(lián),大家井水不犯河水,互不干涉、互不影響,最好克隆一個(gè)一模一樣的新數(shù)組出來。Java恰巧給每個(gè)數(shù)組變量都提供了clone方法,該方法正是拿來克隆數(shù)組用的。克隆出來的新數(shù)組分配了單獨(dú)的存儲空間,并且數(shù)組元素的數(shù)值與原數(shù)組完全一致,如此便實(shí)現(xiàn)了正常意義上的數(shù)組賦值功能。利用clone方法復(fù)制數(shù)組變量的示例代碼如下:
// 復(fù)制數(shù)組的第二個(gè)辦法:調(diào)用原數(shù)組的clone方法。新數(shù)組由原數(shù)組克隆而來 int[] pricesClone=pricesOrigin.clone(); pricesOrigin[1]=80; for (int price : pricesClone) { // 循環(huán)遍歷并打印整型數(shù)組的所有元素?cái)?shù)值 System.out.println("clone price="+price); }
運(yùn)行以上示例代碼,得到下面的日志輸出結(jié)果:
clone price=99
clone price=99
clone price=99
clone price=99
clone price=99
可見此時(shí)修改了原數(shù)組的元素值,并沒有改變新數(shù)組的元素值,真正做到了完整的復(fù)制操作。
clone方法正如其名,它把原數(shù)組的所有元素一個(gè)不漏地全部復(fù)制到新數(shù)組,這意味著,如果只想復(fù)制部分元素給新數(shù)組,clone方法就無能為力了。為此,Java給Arrays工具增配了一個(gè)copyOf方法,該方法允許從來源數(shù)組復(fù)制若干元素給目標(biāo)數(shù)組。當(dāng)待復(fù)制的元素個(gè)數(shù)恰好等于原數(shù)組的大小時(shí),copyOf方法的作用等同于數(shù)組變量的clone方法。下面是通過copyOf方法將數(shù)組原樣復(fù)制到新數(shù)組的代碼例子:
// 復(fù)制數(shù)組的第3個(gè)辦法:調(diào)用Arrays工具的copyOf方法。允許復(fù)制部分元素 int[] pricesCopy=Arrays.copyOf(pricesOrigin, pricesOrigin.length); for (int price : pricesCopy) { // 循環(huán)遍歷并打印整型數(shù)組的所有元素?cái)?shù)值 System.out.println("copy price="+price); }
從上面的代碼看到,copyOf方法后面跟著兩個(gè)參數(shù):第一個(gè)參數(shù)是原數(shù)組的名稱;第二個(gè)參數(shù)是要復(fù)制的元素個(gè)數(shù)。接下來,把第二個(gè)參數(shù)改小一點(diǎn),看看copyOf方法是否真的支持只復(fù)制部分元素。于是第二個(gè)參數(shù)改為pricesOrigin.length-1之后的代碼如下:
// 改變copyOf方法的第二個(gè)參數(shù)值,允許復(fù)制指定大小的數(shù)組元素 int[] pricesPart=Arrays.copyOf(pricesOrigin, pricesOrigin.length-1); for (int price : pricesPart) { // 循環(huán)遍歷并打印整型數(shù)組的所有元素?cái)?shù)值 System.out.println("part price="+price); }
重新運(yùn)行修改后的數(shù)組復(fù)制代碼,日志輸出結(jié)果如下:
part price=99
part price=99
part price=99
part price=99
可以看到新數(shù)組的元素只有4個(gè),而原數(shù)組共有5個(gè)元素,說明此時(shí)的確只復(fù)制了部分元素。
Arrays工具的copyOf方法還有一個(gè)妙用,比如有一個(gè)數(shù)組分配了初始大小為5,現(xiàn)在想把該數(shù)組的長度擴(kuò)大到10,這時(shí)利用copyOf方法就能動態(tài)調(diào)整數(shù)組的大小。具體做法是:調(diào)用copyOf方法時(shí),來源數(shù)組和目標(biāo)數(shù)組都填該數(shù)組的名稱,然后待復(fù)制的元素大小填寫擴(kuò)大后的長度。下面的代碼將演示如何將某數(shù)組的大小增大一位:
// 把copyOf方法的返回值賦給原數(shù)組,可以動態(tài)調(diào)整該數(shù)組的大小 pricesOrigin=Arrays.copyOf(pricesOrigin, pricesOrigin.length+1); for (int price : pricesOrigin) { // 循環(huán)遍歷并打印整型數(shù)組的所有元素?cái)?shù)值 System.out.println("origin price="+price); }
運(yùn)行調(diào)整數(shù)組大小的演示代碼,觀察到以下的日志輸出:
origin price=99
origin price=99
origin price=99
origin price=99
origin price=99
origin price=0
由此可見,數(shù)組大小果然增大了一位,并且新增的數(shù)組元素值為0,這正是整型變量的默認(rèn)數(shù)值。
4.Arrays.sort方法
顧名思義,Arrays工具的sort方法是給數(shù)組元素排序的,并且默認(rèn)的排序結(jié)果為升序。sort方法用起來很簡單,只要把待排序的數(shù)組名稱填進(jìn)圓括號,編譯器就會自動完成該數(shù)組的排序任務(wù)。舉一個(gè)給整型數(shù)組排序的例子,簡單的Java實(shí)現(xiàn)代碼如下:
int[] prices={ 99, 80, 18, 68, 8 }; // 對整型數(shù)組prices里的元素排序,sort方法得到的結(jié)果是升序排列 Arrays.sort(prices); for (int price : prices) { // 循環(huán)遍歷并打印整型數(shù)組的所有元素?cái)?shù)值 System.out.println("price=" + price); }
運(yùn)行上述的排序代碼,得到下面的結(jié)果日志:
price=8
price=18
price=68
price=80
price=99
從日志看到,排序后的數(shù)組元素從小到大打印,很明顯這是升序排列。
當(dāng)然,在前面的例子中,數(shù)組元素早在聲明數(shù)組時(shí)便初始化賦值了,實(shí)戰(zhàn)性不強(qiáng)。接下來,嘗試動態(tài)生成一個(gè)隨機(jī)數(shù)數(shù)組,再對該數(shù)組排序,這樣更貼近實(shí)際業(yè)務(wù)。詳細(xì)的實(shí)現(xiàn)代碼涉及數(shù)組、循環(huán)、冒號跳轉(zhuǎn)等技術(shù),有興趣的讀者不妨動手實(shí)踐。下面是生成隨機(jī)數(shù)組并對其排序的代碼例子(完整代碼見本章源碼的src\com\control\array\ArraySort.java):
int[] numbers=new int[10]; // 創(chuàng)建一個(gè)大小為10的整型數(shù)組 loop: for (int i=0; i < numbers.length; i++) { int item=new Random().nextInt(100); // 生成一個(gè)小于100的隨機(jī)整數(shù) // 下面的循環(huán)用來檢查數(shù)組中是否已經(jīng)存在該隨機(jī)數(shù) for (int j=0; j < i; j++) { if (numbers[j] == item) { // 若已經(jīng)存在該隨機(jī)數(shù),則繼續(xù)第一層循環(huán),重新生成隨機(jī)數(shù) i--; // 本次循環(huán)做了無用功,取消當(dāng)前的計(jì)數(shù) continue loop; // 繼續(xù)以loop標(biāo)記的外層循環(huán) } } numbers[i]=item; // 若原數(shù)組不存在該隨機(jī)數(shù),則把隨機(jī)數(shù)加入數(shù)組中 } // 對整型數(shù)組numbers里的元素排序,sort方法得到的結(jié)果是升序排列 Arrays.sort(numbers); for (int number : numbers) { // 循環(huán)遍歷并打印整型數(shù)組的所有隨機(jī)數(shù) System.out.println("number=" + number); }
- Mastering Concurrency Programming with Java 8
- Python自然語言處理實(shí)戰(zhàn):核心技術(shù)與算法
- Java Web基礎(chǔ)與實(shí)例教程(第2版·微課版)
- Vue.js 3.x從入門到精通(視頻教學(xué)版)
- Web Development with Django Cookbook
- 實(shí)戰(zhàn)低代碼
- Silverlight魔幻銀燈
- Python完全自學(xué)教程
- TypeScript項(xiàng)目開發(fā)實(shí)戰(zhàn)
- 前端HTML+CSS修煉之道(視頻同步+直播)
- C/C++程序員面試指南
- Scala Data Analysis Cookbook
- Flink入門與實(shí)戰(zhàn)
- Building Apple Watch Projects
- JBoss AS 7 Development