美文网首页
java中list循环时删除元素

java中list循环时删除元素

作者: 蛋黄也可以很有派 | 来源:发表于2020-05-13 22:43 被阅读0次

如何一边循环一边删除数组中的元素?

坑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循环。但是这个解决方法里还是隐藏了一个坑。

坑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的源码:

/**

* Returns a fixed-size list backed by the specified array.  (Changes to

* the returned list "write through" to the array.)  This method acts

* as bridge between array-based and collection-based APIs, in

* combination with {@link Collection#toArray}.  The returned list is

* serializable and implements {@link RandomAccess}.

*

* <p>This method also provides a convenient way to create a fixed-size

* list initialized to contain several elements:

* <pre>

*    List&lt;String&gt; stooges = Arrays.asList("Larry", "Moe", "Curly");

* </pre>

*

* @param <T> the class of the objects in the array

* @param a the array by which the list will be backed

* @return a list view of the specified array

*/

@SafeVarargs

@SuppressWarnings("varargs")

public static <T> List<T> asList(T... a) {

    return new ArrayList<>(a);

}

单从代码看:return new ArrayList<>(a);应该是一个普通的ArrayList啊?!查看注释:返回一个固定大小的list!也就是说add和remove操作肯定会报错。同时也说明了这里的ArrayList不是我们平时使用的ArrayList。继续跟踪这个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的一个实现了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);

}

反思

通过踩这几个坑,再次验证了一个真理:在设计一个对外方法的时候,一点要谨慎处理集合和数组。因为你永远不知道客户端传给你的集合是什么,也不知道客户端是否会有对此集合有任何其他的不可控的操作。所以在使用客户端传递的集合对象时,最好拷贝一个新集合后再操作。

转载自

https://zacard.net/2016/01/07/list-remove/

相关文章

网友评论

      本文标题:java中list循环时删除元素

      本文链接:https://www.haomeiwen.com/subject/jpjanhtx.html