下面列出Stack Overflow上最多見的幾個關於Java Collections的問題並給出答案。java
ArrayList
是使用數組實現的list,本質上就是數組。ArrayList中的元素能夠經過索引隨機獲取一個元素。可是若是該數組已滿,當添加新元素時須要分配一個新的數組而後將原來數組的元素移動過去,須要O(n)的時間複雜度。添加或刪除一個元素須要移動數組中的其餘元素。這是ArrayList最大的缺點。數組
LinkedList
是一個雙向鏈表。所以,當須要獲取list中某個元素,須要從頭至尾遍歷list。另外一方面,在鏈表中添加或刪除元素很快,只須要O(1)的時間複雜度。從空間上來講,在鏈表中一個節點須要兩個額外的指針來指向它的previous和next節點。性能
總結:線程
從時間複雜度來講,若是對list增長或刪除操做較多,優先用LinkedList;若是查詢操做較多,優先用ArrayList。指針
從空間複雜度來講,LinkedList會佔用較多空間。code
邊遍歷邊修改Collection的惟一正確方式是使用Iterator.remove()
方法,以下:對象
Iterator<Integer> it = list.iterator(); while(it.hasNext()){ // do something it.remove(); }
一種最多見的錯誤代碼以下:排序
for(Integer i : list){ list.remove(i) }
運行以上錯誤代碼會報ConcurrentModificationException
異常。這是由於當使用foreach
(for(Integer i : list))語句時,會自動生成一個iterator來遍歷該list,但同時該list正在被Iterator.remove()
修改。在Java中,通常不容許一個線程在遍歷collection時另外一個線程在修改它。索引
不少人可能認爲只需用List.toArray()
便可,其實否則。List.toArray()方法只可能獲得Integer[],沒法獲得int[]。接口
最簡單的方法是使用Apache Commons Lang
庫中的ArrayUtils
。
int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0]));
在JDK中,沒有捷徑。須要注意的是,不能直接使用List.toArray()
,由於這樣會將List轉化成Integer[]而不是int[]。正確的作法以下:
int[] array = new int[list.size()]; for(int i = 0; i < list.size(); i++){ array[i] = list.get(i); }
同上,不少人覺得只需用Arrays.asList()
便可,其實否則。由於不能以int[]做爲該方法的參數,要的話也只能是Integer[]。
關於Arrays.asList()
方法有以下特性:
那麼如何將int[]轉化成List呢?
仍是得本身實現:
int[] array = {1,2,3,4,5}; List<Integer> list = new ArrayList<Integer>(); for(int i: array) { list.add(i); }
如過濾掉list中大於5的整數。
Iterator<Integer> it = list.iterator(); while(it.hasNext()){ int i = it.next(); if(i > 5) { //過濾掉大於5的整數 it.remove(); } }
有兩種方法,取決於你怎麼要怎麼定義兩個元素相等。第一種方法是將list放入HashSet
裏,該方法元素是否相等是經過它們的hashCode()來比較的。若是須要本身定義比較的方法,須要用TreeSet
。
Set<Integer> set = new HashSet<Integer>(list);
Set<Integer> set = new TreeSet<Integer>(aComparator); set.addAll(list);
若是不關心元素在ArrayList中的順序,能夠將list放入set中來刪除重複元素,而後在放回list。
Set<Integer> set = new HashSet<Integer>(list); list.clear(); list.addAll(set);
若是關心元素在ArrayList中的順序,能夠用LinkedHashSet
。
Java裏有不少方法來維持一個collection有序。有的須要實現Comparable接口,有的須要本身指定Comparator。
Collections.sort()
能夠用來對list排序。該排序是穩定的,而且能夠保證nlog(n)的性能。PriorityQueue
提供排序的隊列。PriorityQueue
和Collections.sort()
的區別是,PriorityQueue
動態維護一個有序的隊列(每添加或刪除一個元素就會從新排序),可是隻能獲隊列中的頭元素。TreeSet
是另外一個選擇。跟PriorityQueue
同樣的是,TreeSet
也動態維護一個有序的集合。能夠從TreeSet
中獲取最大和最小的元素。總結:Collections.sort()
提供一個一次排序的list。PriorityQueue
和TreeSet
動態維護排序的collection。
有兩種方法能夠用來拷貝list。一種是使用ArrayList
構造器。
ArrayList<Integer> dstList = new ArrayList<Integer>(srcList);
另外一種是使用Collections.copy()
。
ArrayList<Integer> dstList = new ArrayList<Integer>(srcList.size()); Collections.copy(dstList, srcList);
須要注意的是,使用該方法的話目標list至少跟源list長度同樣長。不然會報IndexOutOfBoundsException
異常。
另外有兩點須要注意:
Collections.copy()
方法的兩個參數必須都是list,而ArrayList
方法參數只要是collection便可,所以ArrayList
方法更通用。 掃一掃關注公衆號: FullStackPlan 獲取更多幹貨哦~