如何一边循环一边删除数组中的元素?
坑1
请看如下代码:
/**
* 测试删除集合中的空白元素
*/
@Test
public void removeBlank() {
List
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
list.add("1");
list.add("2");
list.add("3");
list.add(" ");
list.add(" ");
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
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}.
*
*
This method also provides a convenient way to create a fixed-size
* list initialized to contain several elements:
*
* List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
*
*
* @param
* @param a the array by which the list will be backed
* @return a list view of the specified array
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static
return new ArrayList<>(a);
}
单从代码看:return new ArrayList<>(a);应该是一个普通的ArrayList啊?!查看注释:返回一个固定大小的list!也就是说add和remove操作肯定会报错。同时也说明了这里的ArrayList不是我们平时使用的ArrayList。继续跟踪这个ArrayList:
/**
* @serial include
*/
private static class ArrayList
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
List
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/