1.性能考慮,優先選擇數組
數組在項目開發當中使用的頻率是越來越少,特別是在業務為主的開發當中,首先數組沒有List,Set等集合提供的諸多方法,查找增加算法都要自己編寫,極其繁瑣麻煩,但由于List,Set等集合使用泛型支持后,存放的都為包裝類,而數組是可以使用基本數據類型,而使用基本數據類型的執行運算速度要比包裝類型快得多,而且集合類的底層也是通過數組進行實現.
2.若有必要,使用變長數組
在學習集合類當中,很多人喜歡將數組的定長拿來和集合類型的自變長來做比較,但其實這種比較并不合適,通過觀察集合類例如ArrayList的實現其實可以看出,所謂的集合變長,其實只是用婉轉的方式對原數組進行了擴容
public static T[] expandCapacity(T[] data, int newLength) {
// 判斷是否為負值
newLength = newLength < 0 ? 0 : newLength;
// 生成新數組,拷貝原值并制定長度
return Arrays.copyOf(data, newLength);
}
3.警惕數組的淺拷貝
數組的淺拷貝在Java編程中亦是基礎中的基礎,淺拷貝是在為數組拷貝時,基本類型拷貝的是值,而引用類型拷貝的是引用地址,在上面的例子當中,拷貝數組使用的Arrays.copyOf為淺拷貝,在使用時需要注意
4.在明確的場景下,為集合指定初始容量
在我們平常的使用當中,因為集合類型是自動變長的,所以基本創建對象時不會為集合類附上初始值,就拿我們最常用的ArrayList來說明,我們首先要知道,當集合容量到達臨界點時,會將底層的數組進行copyOf的操作,生成新的數組,而新的數組容量為舊數組的1.5倍,而默認數組長度為10,當我們明確知道要放置入容器中的數據數量較多時,應該指明初始值,避免多次使用copyOf造成的性能開銷
5.選擇合適的最值算法
對數據進行最大值或最小值的查找,這是數據結構最基本的知識,在Java當中我們亦有很多種的方式進行實現,以下列舉2種算法
public static int getMaxByArray(int[] data) {
// 最簡單自行實現的查找方式
int max = data[0];
for (int i = 1, size = data.length; i < size; i++) {
max = max < i ? i : max;
}
return max;
}
// 先排序后獲取最后位
Arrays.sort(data);
return data[data.length - 1];
}
請觀察以下代碼
int[] nums = new int[] { 1, 2, 3, 4, 5 };
List list = Arrays.asList(nums);
System.out.println(list.size());
// 此時輸出的size為1
}
7.asList方法產生的List對象不可更改
通過上面的例子,我們可以看到使用Arrays.asList方法可以將一個數組轉換成一個List,那通過asList方法返回的List有什么特別呢?注意,這個返回的List是不支持更改的,原因是因為asList方法返回的,并不是java.util.ArrayList,而是Arrays工具類中的一個靜態私有內部類,雖然都有實現和ArrayList一樣的父類AbstractList,但在復寫add等方法時,卻是拋出了UnsupportedOperationException,這個靜態私有內部類只實現了size,toArray,get,contains這幾個方法
8.對不同的數據結構使用不同的遍歷方式
請觀看以下代碼
public static void main(String[] args) {
// 以下為ArrayList集合的遍歷方式
int num = 80 * 10000;
List arrayList = new ArrayList(num);
for (int i = 0, size = arrayList.size(); i < size; i++) {
arrayList.get(i);
}
// 以下為LinkedList集合的遍歷方式
List linkedList = new LinkedList();
for (Integer integer : linkedList) {
}
}
1.因為ArrayList實現了RamdomAccess接口(隨機存取接口),RamdomAccess接口和Serializable,Cloneable接口一樣是Java中的標示接口,代表這個這個類可以隨機存取,對ArrayList來說就標志著,數據之間沒有關聯,即相鄰的兩個位置沒有互相依賴的關系,可以隨機訪問,
2.Java中的foreach語法是iterator(迭代器)的變形用法,我們知道迭代器是23種設計模式的一種,但迭代器是需要知道兩個元素時間的關系的,不然怎么提供hasNext的支持呢?就是因為上一個元素要判斷下一個元素是否存在,強行建立了這種關系,違背了ArrayList隨機存取的特別
3.在LinkedList中,因為是通過雙向鏈表的形式來存儲,所以對迭代器的支持非常好,因為LinkedList相鄰的兩個元素本來就存在關系所以在對LinkedList和ArrayList要采取不同的遍歷方式,讀者若然有興趣可以嘗試一下對LinkedList采用下標的形式訪問,會發現兩者的效率有較大的差距
8.適時選擇ArrayList或LinkedList
ArrayList和LinkedList的主要區別:
1.ArrayList底層的數據結構為數組,而LinkedList底層結構為雙向鏈表
2.在插入數據時,由于ArrayList每次插入后都需要將數組元素向后順延位置,而LinkedList只需要更改頭節點和尾節點即可完成插入操作,所以在插入操作較為頻繁時,優先使用LinkedList
3.在刪除數據時,由于ArrayList要保持數組的有序性,當刪除后元素要亦需要向后或向前移位,而LinkedList照舊還是更改頭尾節點.
4.在更新時,由于LinkedList會使用折半遍歷的方式進行查找定位元素再進行更新,對比起ArrayList的直接定位下標元素替換,ArrayList對更新的效率更佳
5.LinkedList可以模擬隊列,通過LinkedList的addFirst,addLast等操作
9.列表相等只需關心元素數據
Java為了我們可以安心的面向List,Set,Map等接口進行編程,因此對集合類中的equlas進行了復寫,讓我們在比較兩個集合是否相等時,只需要比較元素數據是否相等即可,避免了因為替換集合實現類造成的錯誤Java代碼
List arrayList = new ArrayList();
arrayList.add(1);
arrayList.add(2);
List linkedList = new LinkedList();
linkedList.add(1);
linkedList.add(2);
System.out.println(arrayList.equals(linkedList));
// 不用關心具體實現,輸出為true
}
新聞熱點
疑難解答