list.remove() 移除元素的底层
话不多说,先上代码:
public class test { public static void main(String[] args) { String str1 = new String("abcde"); String str2 = new String("abcde"); String str3 = new String("abcde"); String str4 = new String("abcde"); String str5 = new String("abcde"); List list = new ArrayList(); list.add(str1); list.add(str2); list.add(str3); list.add(str4); list.add(str5); System.out.println("list.size()=" + list.size()); for (int i = 0; i < list.size(); i++) { if (((String) list.get(i)).startsWith("abcde")) { list.remove(i); } } System.out.println("after remove:list.size()=" + list.size()); } }
大家猜猜会是什么结果?
不是就这样吗?
list.size()=5 after remove:list.size()=0
但实际是这样的
list.size()=5 after remove:list.size()=2
为什么会这样呢?让我们来看看list.remove()到底做了什么
public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } private void fastRemove(int index) { modCount++; 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 } public static native void arraycopy(Object src, int srcPos, Object dest, int destPos,int length);
可以看到,List每remove掉一个元素以后,后面的元素都会向前移动。
现在回过头看看刚开始写的代码,在remove后,如果执行i=i+1,则刚刚移过来的元素没有被读取。所以就会有两个元素漏掉了。