- Vector?v?=?new?Vector(); ??
- for(int?i=0;i<10;i++) ??
- ????v.add(new?Integer(i)); ??
- ??
- Enumeration?e?=?v.elements(); ??
- ??
- while(e.hasMoreElements()) ??
- { ??
- ????Integer?i?=?(Integer)e.nextElement(); ??
- ????v.remove(i); ??
- ???????? ??
- } ??
- ??
- System.out.println(v.size());??
Vector v = new Vector(); for(int i=0;i<10;i++) v.add(new Integer(i)); Enumeration e = v.elements(); while(e.hasMoreElements()) { Integer i = (Integer)e.nextElement(); v.remove(i); } System.out.println(v.size());
如果没去执行这段程序,可能有的人会认为
System.out.println(v.size());
输出来的是0,但实际上是5,为什么会这样的呢?
在回答这个问题前,我们先看看2段代码
- ???public?Enumeration<E>?elements()?{ ??
- return?new?Enumeration<E>()?{ ??
- ????int?count?=?0; ??
- ??
- ????public?boolean?hasMoreElements()?{ ??
- ????return?count?<?elementCount; ??
- ????} ??
- ??
- ????public?E?nextElement()?{ ??
- ????synchronized?(Vector.this)?{ ??
- ????????if?(count?<?elementCount)?{ ??
- ????????return?(E)elementData[count++]; ??
- ????????} ??
- ????} ??
- ????throw?new?NoSuchElementException("Vector?Enumeration"); ??
- ????} ??
- }; ??
- ???}??
public Enumeration<E> elements() { return new Enumeration<E>() { int count = 0; public boolean hasMoreElements() { return count < elementCount; } public E nextElement() { synchronized (Vector.this) { if (count < elementCount) { return (E)elementData[count++]; } } throw new NoSuchElementException("Vector Enumeration"); } }; }
上面这段代码就是v.elements()代码
- public?synchronized?void?removeElementAt(int?index)?{ ??
- ????modCount++; ??
- ????if?(index?>=?elementCount)?{ ??
- ????????throw?new?ArrayIndexOutOfBoundsException(index?+?"?>=?"?+ ??
- ?????????????????????????????elementCount); ??
- ????} ??
- ????else?if?(index?<?0)?{ ??
- ????????throw?new?ArrayIndexOutOfBoundsException(index); ??
- ????} ??
- ????int?j?=?elementCount?-?index?-?1; ??
- ????if?(j?>?0)?{ ??
- ????????System.arraycopy(elementData,?index?+?1,?elementData,?index,?j); ??
- ????} ??
- ????elementCount--; ??
- ????elementData[elementCount]?=?null;?/*?to?let?gc?do?its?work?*/??
- ????}??
public synchronized void removeElementAt(int index) { modCount++; if (index >= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); } else if (index < 0) { throw new ArrayIndexOutOfBoundsException(index); } int j = elementCount - index - 1; if (j > 0) { System.arraycopy(elementData, index + 1, elementData, index, j); } elementCount--; elementData[elementCount] = null; /* to let gc do its work */ }
上面这段代码,就是v.remove(Object o)的主核心代码
分析:
先看第一段代码:
从代码中,我们得知Enumenation.nextElement 会将指针下划到下一个元素
在看第二段代码:
从代码中,我们得知v.remove 进行操作时,是将后面的数组覆盖掉 所要删除元素的位置,最后一个则用null
现在我们理顺下思路吧,
v 里面存放的数是 0 1 2 3 4 5 6 7 8 9
首先e.nextElement() 指针所在位置就是 0,也就是数组的第一个索引
当我们进行v.reomve的时候,后面的数组覆盖了前面的数组
v.remove 处理完后: 1 2 3 4 5 6 7 8 9
这时候,进入下次循环
e.nextElement() 这时候的指针位置就是 2, 而漏过了 1 这个数据,
循环结束后,就漏掉了5个数,
所以,大家在做这样的remove的时候,需要特别注意下