关于Java Collections的几个常见问题
列舉幾個(gè)關(guān)于Java Collections的常見問題并給出答案。
1. 什么時(shí)候用LinkedList,什么時(shí)候用ArrayList?
ArrayList是使用數(shù)組實(shí)現(xiàn)的list,本質(zhì)上就是數(shù)組。ArrayList中的元素可以通過索引隨機(jī)獲取一個(gè)元素。但是如果該數(shù)組已滿,當(dāng)添加新元素時(shí)需要分配一個(gè)新的數(shù)組然后將原來數(shù)組的元素移動(dòng)過去,需要O(n)的時(shí)間復(fù)雜度。添加或刪除一個(gè)元素需要移動(dòng)數(shù)組中的其他元素。這是ArrayList最大的缺點(diǎn)。
LinkedList是一個(gè)雙向鏈表。因此,當(dāng)需要獲取list中某個(gè)元素,需要從頭到尾遍歷list。另一方面,在鏈表中添加或刪除元素很快,只需要O(1)的時(shí)間復(fù)雜度。從空間上來說,在鏈表中一個(gè)節(jié)點(diǎn)需要兩個(gè)額外的指針來指向它的previous和next節(jié)點(diǎn)。
總結(jié):
從時(shí)間復(fù)雜度來說,如果對list增加或刪除操作較多,優(yōu)先用LinkedList;如果查詢操作較多,優(yōu)先用ArrayList。
從空間復(fù)雜度來說,LinkedList會(huì)占用較多空間。
2. 如何邊遍歷邊移除Collection中的元素
邊遍歷邊修改Collection的唯一正確方式是使用Iterator.remove()方法,如下:
| 1 2 3 4 5 | Iterator<Integer> it = list.iterator(); while(it.hasNext()){ ????// do something ????it.remove(); } |
一種最常見的錯(cuò)誤代碼如下:
| 1 2 3 | for(Integer i : list){ ????list.remove(i) } |
運(yùn)行以上錯(cuò)誤代碼會(huì)報(bào)ConcurrentModificationException異常。這是因?yàn)楫?dāng)使用foreach(for(Integer i : list))語句時(shí),會(huì)自動(dòng)生成一個(gè)iterator來遍歷該list,但同時(shí)該list正在被Iterator.remove()修改。在Java中,一般不允許一個(gè)線程在遍歷collection時(shí)另一個(gè)線程在修改它。
3. 如何將List轉(zhuǎn)化成int[]?
很多人可能認(rèn)為只需用List.toArray()即可,其實(shí)不然。List.toArray()方法只可能得到Integer[],無法得到int[]。
最簡單的方法是使用Apache Commons Lang庫中的ArrayUtils。
| 1 | int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0])); |
在JDK中,沒有捷徑。需要注意的是,不能直接使用List.toArray(),因?yàn)檫@樣會(huì)將List轉(zhuǎn)化成Integer[]而不是int[]。正確的做法如下:
| 1 2 3 4 | int[] array = new int<div class="list "></div>; for(int i = 0; i < list.size(); i++){ ????array[i] = list.get(i); } |
4. 如何將int[]轉(zhuǎn)化成List?
同上,很多人以為只需用Arrays.asList()即可,其實(shí)不然。因?yàn)椴荒芤詉nt[]作為該方法的參數(shù),要的話也只能是Integer[]。
關(guān)于Arrays.asList()方法有如下特性:
- 1.該方法對于基本數(shù)據(jù)類型的數(shù)組支持并不好,當(dāng)數(shù)組是基本數(shù)據(jù)類型時(shí)不建議使用
- 2.當(dāng)使用asList()方法時(shí),數(shù)組就和列表鏈接在一起了。當(dāng)更新其中之一時(shí),另一個(gè)將自動(dòng)獲得更新。因?yàn)閍sList獲得的List實(shí)際引用的就是數(shù)組 注意:僅僅針對對象數(shù)組類型,基本數(shù)據(jù)類型數(shù)組不具備該特性。
- 3.asList得到的數(shù)組是的沒有add和remove方法的。因?yàn)閍sList返回的List是Arrays中的內(nèi)部類,而該類并沒有定義add和remove方法。
那么如何將int[]轉(zhuǎn)化成List呢?
還是得自己實(shí)現(xiàn):
| 1 2 3 4 5 | int[] array = {1,2,3,4,5}; List<Integer> list = new ArrayList<Integer>(); for(int i: array) { ??list.add(i); } |
5. 過濾一個(gè)Collection最好的方法是什么?
如過濾掉list中大于5的整數(shù)。
| 1 2 3 4 5 6 7 | Iterator<Integer> it = list.iterator(); while(it.hasNext()){ ????int i = it.next(); ????if(i > 5) {? //過濾掉大于5的整數(shù) ????????it.remove(); ????} } |
6. 將List轉(zhuǎn)化成Set最簡單的方法?
有兩種方法,取決于你怎么要怎么定義兩個(gè)元素相等。第一種方法是將list放入HashSet里,該方法元素是否相等是通過它們的hashCode()來比較的。如果需要自己定義比較的方法,需要用TreeSet。
| 1 | Set<Integer> set = new HashSet<Integer>(list); |
| 1 2 | Set<Integer> set = new TreeSet<Integer>(aComparator); set.addAll(list); |
7. 如何刪除ArrayList中重復(fù)的元素?
如果不關(guān)心元素在ArrayList中的順序,可以將list放入set中來刪除重復(fù)元素,然后在放回list。
| 1 2 3 | Set<Integer> set = new HashSet<Integer>(list); list.clear(); list.addAll(set); |
如果關(guān)心元素在ArrayList中的順序,可以用LinkedHashSet。
8. 有序的collection
Java里有很多方法來維持一個(gè)collection有序。有的需要實(shí)現(xiàn)Comparable接口,有的需要自己指定Comparator。
總結(jié):Collections.sort()提供一個(gè)一次排序的list。PriorityQueue和TreeSet動(dòng)態(tài)維護(hù)排序的collection。
9. 拷貝list
有兩種方法可以用來拷貝list。一種是使用ArrayList構(gòu)造器。
| 1 | ArrayList<Integer> dstList = new ArrayList<Integer>(srcList); |
另一種是使用Collections.copy()。
| 1 2 | ArrayList<Integer> dstList = new ArrayList<Integer>(srcList.size()); Collections.copy(dstList, srcList); |
需要注意的是,使用該方法的話目標(biāo)list至少跟源list長度一樣長。否則會(huì)報(bào)IndexOutOfBoundsException異常。
另外有兩點(diǎn)需要注意:
轉(zhuǎn)載于:https://www.cnblogs.com/baizhanshi/p/6482923.html
總結(jié)
以上是生活随笔為你收集整理的关于Java Collections的几个常见问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云服务器部署网易云音乐API(node.
- 下一篇: Java名字的由来