先給不熟悉的兄弟們科普一下:
Array.asList()方法用于将數組轉化為集合
對于經常做資料處理的朋友來說
應該并不陌生
不過話說回來
這個方法有幾個隐藏的"坑"
可能有兄弟會中招
咱們接下來就一探究竟
聽說點贊分享效果更佳呢!!
坑一:不能直接轉換基本資料類型的數組
錯誤案例:
//定義基本資料類型int類數組
int[] arr = {1, 2, 3};
//使用Array.asList()方法轉換為集合
List list = Arrays.asList(arr);
//輸出轉換之後的集合資訊
log.info("list:{} size:{}", list, list.size());
複制
期望輸出:
list:[1, 2, 3] size:3
複制
控制台實際輸出:
list:[[I@1c53fd30] size:1
複制
很明顯隐藏的”坑“出現了,
擁有三個元素的數組在轉換之後隻剩一個元素且資料類型有問題。
原因分析:
雖然int可以裝箱為包裝類integer,但int數組則無法整體裝箱成integer數組。
脫坑方案:
1、Java8以上提供了Arrays.stream方法強制轉換
int[] arr1 = {1, 2, 3};
List list1 = Arrays.stream(arr1).boxed().collect(Collectors.toList());
log.info("list:{} size:{}", list1, list1.size());
複制
2、直接使用包裝類integer定義數組
Integer[] arr2 = {1, 2, 3};
List list2 = Arrays.asList(arr2);
log.info("list:{} size:{}", list2, list2.size());
複制
修改之後的控制台輸出:
list:[1, 2, 3] size:3
複制
得到了我們期望的結果,第一個坑我們就脫坑成功啦!
兄弟不要吝啬你的點贊哦!是我繼續輸出的動力,我們繼續脫坑:
坑二:轉換之後的集合無法增删元素
錯誤案例:
//這次我們用引用類String數組
String[] arr = {"1", "2", "3"};
List list = new ArrayList(Arrays.asList(arr));
try {
//嘗試向轉換後的list追加元素
list.add("5");
} catch (Exception ex) {
ex.printStackTrace();
}
//轉換之後,修改原數組的值
arr[1] = "4";
//輸出原數組、轉換後的集合
log.info("arr:{} list:{}", Arrays.toString(arr), list);
複制
期望輸出:
arr:[1, 4, 3] list:[1, 2, 3, 5]
複制
控制台實際輸出:
//首先是list追加元素的異常
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at org.geekbang.time.commonmistakes.collection.aslist.AsListApplication.wrong2(AsListApplication.java:41)
at org.geekbang.time.commonmistakes.collection.aslist.AsListApplication.main(AsListApplication.java:15)
//元素輸出
arr:[1, 4, 3] list:[1, 4, 3]
複制
根據控制台輸出來看,
我們不僅向list追加元素失敗,
我們對原數組中元素的修改也影響到了集合list,
這就是第三個坑點:
坑三:對原始數組的修改會影響轉換之後的List
原因分析:
其實Arrays.asList方法傳回的List并不是我們期望的java.util.ArrayList,而是Arrays的内部類ArrayList。
兩者的差別在于,ArrayList内部類繼承自AbstractList類,并沒有覆寫父類的add方法,是以就産生了上面的異常。
至于第三個坑點則是因為ArrayList直接使用了原始的數組,是以會産生互相共享數組的效果。
如果我們把通過Arrays.asList獲得的List交給其他方法處理,很容易因為共享了數組,互相修改産生隐式的“bug”。
這種問題是很難找原因的,要特别小心。
脫坑方案:
方法其實不難猜想,
我們隻需要用一個真正的java.util.ArrayList來存放轉換之後的list即可
String[] arr = {"1", "2", "3"};
//用java.util.ArrayList接收轉換後的list
List list = new ArrayList(Arrays.asList(arr));
arr[1] = "4";
try {
list.add("5");
} catch (Exception ex) {
ex.printStackTrace();
}
log.info("arr:{} list:{}", Arrays.toString(arr), list);
複制
修改之後的控制台輸出:
arr:[1, 4, 3] list:[1, 2, 3, 5]
複制
輸出符合我們的預期。
我們new的ArrayList既可以做add操作、又和之前的數組實作了分離。
這樣就很好的解決了問題!
end