java list循环中删除元素的坑
背景
當我們要循環(huán)一個list中的元素,并且要刪除某個元素的時候,一點要小心謹慎!其中深埋了好幾個坑!
坑1
請看如下代碼:
/*** 測試刪除集合中的空白元素*/ @Test public void removeBlank() {List<String> list = new ArrayList<>();list.add("1");list.add("2");list.add("3");list.add(" ");list.add(" ");for (String s : list) {if (StringUtils.isBlank(s)) {list.remove(s);}}System.out.println("list:" + list); }輸出結果:list:[1, 2, 3, ] ??梢钥吹娇瞻自貨]有刪除干凈。
坑1解決辦法
請看如下代碼:
/*** 測試刪除集合中的空白元素*/ @Test public void removeBlank() {List<String> list = new ArrayList<>();list.add("1");list.add("2");list.add("3");list.add(" ");list.add(" ");Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {String s = iterator.next();if (StringUtils.isBlank(s)) {iterator.remove();}}System.out.println("list:" + list); }結果輸出:list:[1, 2, 3]。解決辦法其實就是用Iterator迭代器代替for循環(huán)。但是這個解決方法里還是隱藏了一個坑。
坑2
請看如下代碼:
/*** 測試刪除集合中的空白元素*/ @Test public void removeBlank() {List<String> list = Arrays.asList("1","2","3",""," ");Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {String s = iterator.next();if (StringUtils.isBlank(s)) {iterator.remove();}}System.out.println("list:" + list); } 結果會直接報錯:java.lang.UnsupportedOperationException。意思是不支持remove操作。
只是把list的定義換成了Arrays.asList,卻有完全不一樣的運行結果,非常神奇。查看Arrays.asList的源碼:
單從代碼看:return new ArrayList<>(a);應該是一個普通的ArrayList啊?!查看注釋:返回一個固定大小的list!也就是說add和remove操作肯定會報錯。同時也說明了這里的ArrayList不是我們平時使用的ArrayList。繼續(xù)跟蹤這個ArrayList:
/*** @serial include*/ private static class ArrayList<E> extends AbstractList<E>implements RandomAccess, java.io.Serializable {private static final long serialVersionUID = -2764017481108945198L;private final E[] a;ArrayList(E[] array) {a = Objects.requireNonNull(array);}... }原來此處的ArrayList是Arrays的一個實現(xiàn)了AbstractList的內部類,并且沒有覆蓋add和remove方法,默認這2個方法是會直接報“UnsupportedOperationException”的。
坑2解決辦法
既然明白了報錯原因,解決辦法也很明顯了:
/*** 測試刪除集合中的空白元素*/ @Test public void removeBlank() {List<String> list = Arrays.asList("1","2","3",""," ");List<String> result= new ArrayList<>(list);Iterator<String> iterator = result.iterator();while (iterator.hasNext()) {String s = iterator.next();if (StringUtils.isBlank(s)) {iterator.remove();}}System.out.println("list:" + result); }反思
通過踩這幾個坑,再次驗證了一個真理:在設計一個對外方法的時候,一點要謹慎處理集合和數(shù)組。因為你永遠不知道客戶端傳給你的集合是什么,也不知道客戶端是否會有對此集合有任何其他的不可控的操作。所以在使用客戶端傳遞的集合對象時,最好拷貝一個新集合后再操作。
更新-2016.01.17
之前的解決方法中違反了java其中的一個編碼準則:變量的作用范圍越小約好。
請看如下代碼:
@Test public void testForAndWhile() {List<String> names1 = Lists.newArrayList("張三", "李四");Iterator<String> iterator1= names1.iterator();while (iterator1.hasNext()) {String name = iterator1.next();System.out.println("name1:" + name);iterator1.remove();}List<String> names2 = Lists.newArrayList("趙六", "錢七");Iterator<String> iterator2= names2.iterator();while (iterator1.hasNext()) {String name = iterator2.next();System.out.println("name2:" + name);iterator2.remove();} }這段代碼的第二個循環(huán)不會打印任何東西,因為while條件中誤用了第一個循環(huán)中的變量,造成的bug。但是這種bug卻不會有任何編譯錯誤和運行時錯誤,危害甚大。但是只要改成舊版for循環(huán)的形式,就可以很好的避免這種錯誤。
請看如下改進代碼:
@Test public void testForAndWhile() {List<String> names1 = Lists.newArrayList("張三", "李四");for (Iterator<String> iterator= names1.iterator();iterator.hasNext();) {System.out.println("name1:"+iterator.next());iterator.remove();}List<String> names2 = Lists.newArrayList("趙六", "錢七");for (Iterator<String> iterator= names2.iterator();iterator.hasNext();) {System.out.println("name2:"+iterator.next());iterator.remove();} }這個時候,如果錯誤的引用循環(huán)1中的代碼,會有編譯時錯誤,就可以很好的避免這種問題
from:?https://zacard.net/2016/01/07/list-remove/
總結
以上是生活随笔為你收集整理的java list循环中删除元素的坑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java集合类ArrayList循环中删
- 下一篇: JAVA中循环删除集合中元素的方法总结