無水乾貨:Java陣列優秀指南
兩年前,我甚至寫過一篇文章,吐槽陣列在 Java 中挺雞肋的,因為有 List 誰用陣列啊,現在想想那時候的自己好幼稚,好可笑。因為我只看到了表面現象,實際上呢,List 的內部仍然是透過陣列實現的。 |
兩年前,我甚至寫過一篇文章,吐槽陣列在 Java 中挺雞肋的,因為有 List 誰用陣列啊,現在想想那時候的自己好幼稚,好可笑。因為我只看到了表面現象,實際上呢,List 的內部仍然是透過陣列實現的,比如說 ArrayList,在它的原始碼裡可以看到下面這些內容:
/** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ transient Object[] elementData; // non-private to simplify nested class access /** * The size of the ArrayList (the number of elements it contains). * * @serial */ private int size;
陣列在 Java 中,必須算是核心,神一般的存在。
按照 Javadoc 給出的解釋,陣列是一個物件,它包含了一組固定數量的元素,並且這些元素的型別是相同的。陣列會按照索引的方式將元素放在指定的位置上,意味著我們可以透過索引來訪問到這些元素。在 Java 中,索引是從 0 開始的。
我們可以將陣列理解為一個個整齊排列的單元格,每個單元格里面存放著一個元素。
陣列元素的型別可以是基本資料型別(比如說 int、double),也可以是引用資料型別(比如說 String),包括自定義型別的物件。
瞭解了陣列的定義後,讓我們來深入地研究一下陣列的用法。
在 Java 中,陣列的宣告方式有兩種。
先來看第一種:
int[] anArray;
再來看第二種:
int anOtherArray[];
不同之處就在於中括號的位置,是緊跟型別,還是放在變數名的後面。前者比後者的使用頻率更高一些。
接下來就該看看怎麼初始化陣列了,同樣有多種方式可以初始化陣列,比如說最常見的是:
int[] anArray = new int[10];
使用了 new 關鍵字,對吧?這就意味著陣列的確是一個物件。然後,在方括號中指定了陣列的長度,這是必須的。
這時候,陣列中的每個元素都會被初始化為預設值,int 型別的就為 0,Object 型別的就為 null。
另外,還可以使用大括號的方式,直接初始化陣列中的元素:
int anOtherArray[] = new int[] {1, 2, 3, 4, 5};
這時候,陣列的元素分別是 1、2、3、4、5,索引依次是 0、1、2、3、4。
前面提到過,可以透過索引來訪問陣列的元素,就像下面這樣:
anArray[0] = 10; System.out.println(anArray[0]);
透過陣列的變數名,加上中括號,加上元素的索引,就可以訪問到陣列,透過“=”運算子進行賦值。
如果索引的值超出了陣列的界限,就會丟擲 ArrayIndexOutOfBoundException,關於這方面的知識,我之前特意寫過一篇文章,如果你感興趣的話,可以跳轉過去看看。
為什麼會發生ArrayIndexOutOfBoundsException
我覺得原因挺有意思的。
既然陣列的索引是從 0 開始,那就是到陣列的 length - 1 結束,不要使用超出這個範圍內的索引訪問陣列,就不會丟擲陣列越界的異常了。
當陣列的元素非常多的時候,逐個訪問陣列就太辛苦了,所以需要透過遍歷的方式。
int anOtherArray[] = new int[] {1, 2, 3, 4, 5}; for (int i = 0; i < anOtherArray.length; i++) { System.out.println(anOtherArray[i]); }
透過 length 屬性獲取到陣列的長度,然後索引從 0 開始遍歷,就得到了陣列的所有元素。
for (int element : anOtherArray) { System.out.println(element); }
如果不需要關心索引的話(意味著不需要修改陣列的某個元素),使用 for-each 遍歷更簡潔一些。當然,也可以使用 while 和 do-while 迴圈。
可變引數用於將任意數量的引數傳遞給方法:
void varargsMethod(String... varargs) {}
varargsMethod() 方法可以傳遞任意數量的字串引數,可以是 0 個或者 N 個,本質上,可變引數就是透過陣列實現的,為了證明這一點,我們可以透過 jad 反編譯一下位元組碼:
public class VarargsDemo { public VarargsDemo() { } transient void varargsMethod(String as[]) { } }
所以我們其實可以直接將陣列作為引數傳遞給可變引數的方法:
VarargsDemo demo = new VarargsDemo(); String[] anArray = new String[] {"沉默王二", "一枚有趣的程式設計師"}; demo.varargsMethod(anArray);
也可以直接傳遞多個字串,透過逗號隔開的方式:
demo.varargsMethod("沉默王二", "一枚有趣的程式設計師");
List 封裝了很多常用的方法,方便我們對集合進行一些操作,而如果直接運算元組的話,多有不便,因此有時候我們需要把陣列轉成 List。
比較原始的方式,就是透過遍歷陣列的方式,一個個將陣列新增到 List 中。
int[] anArray = new int[] {1, 2, 3, 4, 5}; List aList = new ArrayList<>(); for (int element : anArray) { aList.add(element); }
更優雅的方式是透過 Arrays 類的 asList() 方法:
List aList = Arrays.asList(anArray);
但需要注意的是,該方法返回的 ArrayList 並不是 java.util.ArrayList,它其實是 Arrays 類的一個內部類:
private static class ArrayList extends AbstractList implements RandomAccess, java.io.Serializable{}
如果需要新增元素或者刪除元素的話,最好把它轉成 java.util.ArrayList。
new ArrayList<>(Arrays.asList(anArray));
Java 8 新增了 Stream 流的概念,這就意味著我們也可以將陣列轉成 Stream 進行操作,而不是 List。
String[] anArray = new String[] {"沉默王二", "一枚有趣的程式設計師", "好好珍重他"}; Stream aStream = Arrays.stream(anArray);
也可以直接對陣列的元素進行剪輯,透過指定索引的方式:
Stream anotherStream = Arrays.stream(anArray, 1, 3);
結果包含"一枚有趣的程式設計師"和"好好珍重他",1 這個索引位置包括,3 這個索引位置不包括。
Arrays 類提供了一個 sort() 方法,可以對陣列進行排序。
基本資料型別按照升序排列
實現了 Comparable 介面的物件按照 compareTo() 的排序
來看第一個例子:
int[] anArray = new int[] {5, 2, 1, 4, 8}; Arrays.sort(anArray);
排序後的結果如下所示:
[1, 2, 4, 5, 8]
來看第二個例子:
String[] yetAnotherArray = new String[] {"A", "E", "Z", "B", "C"}; Arrays.sort(yetAnotherArray, 1, 3, Comparator.comparing(String::toString).reversed());
只對 1-3 位置上的元素進行反序,所以結果如下所示:
[A, Z, E, B, C]
有時候,我們需要從陣列中查詢某個具體的元素,比較直接的方式就是透過遍歷的方式:
int[] anArray = new int[] {5, 2, 1, 4, 8}; for (int i = 0; i < anArray.length; i++) { if (anArray[i] == 4) { System.out.println("找到了 " + i); break; } }
上例中從陣列中查詢元素 4,找到後透過 break 關鍵字退出迴圈。
如果陣列提前進行了排序,就可以使用二分查詢法,這樣效率就會更高一些。Arrays.binarySearch() 方法可供我們使用,它需要傳遞一個陣列,和要查詢的元素。
int[] anArray = new int[] {1, 2, 3, 4, 5}; int index = Arrays.binarySearch(anArray, 4);
除了一維陣列,還有二維陣列,但說實話,二維陣列不太常用,這裡就不再介紹了,感興趣的話,可以嘗試列印以下楊輝三角。
這篇文章,我們介紹了 Java 陣列的基本用法和一些高階用法,我想小夥伴們應該已經完全掌握了。
原文地址:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559985/viewspace-2704284/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 無水乾貨:InnoDB底層原理
- 乾貨分享!優秀介面設計技巧(一)
- 乾貨:成為優秀的JAVA工程師必讀的經典書籍Java工程師
- 無水乾貨-如何快速分析Linux伺服器的效能問題Linux伺服器
- 【乾貨】js 陣列詳細操作方法及解析合集JS陣列
- 乾貨|解讀Java併發佇列BlockingQueueJava佇列BloC
- Java列舉:小小enum,優雅而乾淨Java
- 乾貨!前端開發指南20+前端
- 老鼠貨、水貨、貨 海淘防坑指南讓你不中招TF
- Java 陣列最佳指南,快收藏讓它吃灰Java陣列
- Java陣列03:陣列使用Java陣列
- 乾貨分享!三大Java框架的優缺點對比Java框架
- Java 陣列Java陣列
- java——陣列Java陣列
- Java陣列Java陣列
- 留學指南權威乾貨與攻略!
- 【java乾貨】java怎麼寫APPJavaAPP
- JavaScript權威指南-陣列JavaScript陣列
- JavaScript 陣列方法:綜合指南JavaScript陣列
- 初識Java(Java陣列-陣列的基本操作)Java陣列
- BZOJ 4650 [Noi2016]優秀的拆分:字尾陣列陣列
- java日期 java陣列Java陣列
- 乾貨收藏 | 如何優化前端效能?優化前端
- AI客服上線 乾貨 乾貨 全是乾貨!AI
- scala陣列與java陣列對比陣列Java
- 純乾貨分享 —— 大資料入門指南大資料
- 技術乾貨:如何判斷一個整數陣列是否存在重複元素......陣列
- Java的 陣列Java陣列
- Java(二)陣列Java陣列
- JAVA陣列案例!Java陣列
- 【Java】陣列使用Java陣列
- java Arrays陣列Java陣列
- java之陣列Java陣列
- java 陣列(轉)Java陣列
- Java - 7 陣列Java陣列
- 前端優秀實踐不完全指南前端
- 優秀的命令列工具整理(二)命令列
- 優秀的命令列工具整理(三)命令列