java list 转数组_数组转List,一定要小心这个坑!
?關注“Java技術迷”升職加薪不脫發!
在日常開發過程中,數組轉List的使用頻率非常之高。大家可以回想一下,通常你都是怎么轉的呢?用代碼說話,下面來看一段代碼:
public?class?Test?{????public?static?void?main(String[]?args)?{
????????List?list=?Arrays.asList("hello","world");
????????System.out.println(list.remove("hello"));
????}
}
先自己想想這段代碼有沒有問題,使用
List list= Arrays.asList("hello","world");
來創建一個List,然后再使用remove將其移除。從邏輯上來說,確實沒毛病,也有很多人認為這本來就沒問題。下面我們來運行一下上面這段代碼,結果:
很多人估計都不敢相信自己的眼睛,上面這段代碼居然會報錯。
如果我們把上面這段代碼改一下:
public?class?Test?{????public?static?void?main(String[]?args)?{
????????List?list=?new?ArrayList<>();
????????list.add("hello");
????????list.add("world");
????????System.out.println(list.remove("hello"));
????}
}
運行結果:
true奇了怪了吧,這就沒問題了。
我們來看看
Arrays.asList("hello");
這個asList方法到底干了些什么?
public?static??List?asList(T...?a)?{return?new?ArrayList<>(a);}
粗略的看了一下,他返回的不就是ArrayList對象嗎?下面這段代碼也是new一個ArrayList對象。
List list= new ArrayList<>();
為什么上面那段就不行呢?整個java.util.Arrays.ArrayList類有哪些方法
他居然是Arrays的一個靜態內部類。現在可以確認這個
java.util.Arrays.ArrayList和java.util.ArrayList不是同一個。
重點來了,這個靜態內部類里有個final修飾的數組:
private?final?E[]?a;final修飾變量表示此變量是不可修改的。也就是我們上面的remove為什么報錯的原因。居然是因為這個Arrays中的ArrayList中使用的是一個固定大小的數據來存儲數據的,同理我們也可以推斷,不能使用add方法,下面我來試試add方法就知道了。
public?class?Test?{????public?static?void?main(String[]?args)?{
????????List?list=?Arrays.asList("hello","world");
????????System.out.println(list.add("!"));
????}
}
運行結果:
運行結果和我們預期的是一樣的。
另外我們看看java.util.ArrayList源碼:
public?class?ArrayList<E>?extends?AbstractList<E>?implements?List<E>,?RandomAccess,?Cloneable,?java.io.Serializable?{????private?static?final?long?serialVersionUID?=?8683452581122892189L;
????/**
?????*?Default?initial?capacity.
?????*/
????private?static?final?int?DEFAULT_CAPACITY?=?10;
????private?static?final?Object[]?EMPTY_ELEMENTDATA?=?{};
????private?static?final?Object[]?DEFAULTCAPACITY_EMPTY_ELEMENTDATA?=?{};
????transient?Object[]?elementData;
這段代碼有也有個數組用來保存數據:
?transient?Object[]?elementData;人家不是使用final修飾,transient修飾只是和系列化有關系。所以人家java.util.ArrayList是不會報異常的。
上面Arrays.ArrayList中居然沒有add和remove方法。認真的你會發現,它也繼承了AbstractList。進去看看她的源碼:
public?abstract?class?AbstractList<E>?extends?AbstractCollection<E>?implements?List<E>?{????protected?AbstractList()?{
????}
????//這是前面我們使用過,并且拋異常的方法
????public?boolean?add(E?e)?{
????????add(size(),?e);
????????return?true;
????}?
????//上面的add方法調用的是這個方法
????public?void?add(int?index,?E?element)?{
????????//拋異常
????????throw?new?UnsupportedOperationException();
????}
????public?E?remove(int?index)?{
????????//拋異常
????????throw?new?UnsupportedOperationException();
????}
????//其他代碼省略
}
前面已經把java.util.Arrays.ArrayList的方法都看過了,并沒有add和remove,也就是說他沒實現父類的add和remove兩個方法。那就是調用了AbstractList的方法了,所以上面拋的兩個異常是在這里拋出來的。
相反java.util.ArrayList卻老老實實的兩個方法都實現了。
????public?boolean?add(E?e)?{????????ensureCapacityInternal(size?+?1);??//?Increments?modCount!!
????????elementData[size++]?=?e;
????????return?true;
????}?
????public?E?remove(int?index)?{
????????rangeCheck(index);
????????modCount++;
????????E?oldValue?=?elementData(index);
????????int?numMoved?=?size?-?index?-?1;
????????if?(numMoved?>?0)
????????????System.arraycopy(elementData,?index+1,?elementData,?index,
?????????????????????????????numMoved);
????????elementData[--size]?=?null;?//?clear?to?let?GC?do?its?work
????????return?oldValue;
????}
好了,上面問題已經得出了答案。下面來說說應該如何正確使用數組轉List。
正確的姿勢
倒也不是說List list= Arrays.asList("hello");這個不要用,只是你得搞清楚原理,一不小心就會為別人(也可能是自己)留下坑。
方式一:
String[]?strings?=?{"hello",?"world"};List?list?=?new?ArrayList(Arrays.asList(strings));
方式二(推薦):
?String[]?strings?=?{"hello",?"world"};?List?list?=?new?ArrayList<>(strings.length);
?Collections.addAll(list,?strings);
方式三:
原始的方法就是變量數組,然后new 對象ArrayList,遍歷數組,一個一個add進去,這里就不貼代碼了,這是最笨的辦法。
總結
Arrays.asList(strArray)方式將數組轉換為List后,不能增刪改原數組的值,僅作讀取使用;
ArrayList構造器方式,在List的數據量不大的情況下,可以使用;
集合工具類Collections.addAll(),在List的數據量巨大的情況下,優先使用,可以提高操作速度。
不僅是ArrayList,其余List的子類(LinkList/Vector)也可以用同樣的方法實現數組和集合轉變。
關注「Java技術迷」,提升Java技能
總結
以上是生活随笔為你收集整理的java list 转数组_数组转List,一定要小心这个坑!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python2.7与python3的区别
- 下一篇: vant按需引入没样式_传统背景墙早看腻