import java.util.Enumeration;
import java.util.Vector;
public class Test { private int i = 0;
private boolean isBusy;

public Test(int i, boolean isBusy) {
this.i = i;
this.isBusy = isBusy;
}

public static void main(String[] args) {
Vector vector = new Vector();
for (int i = 0; i < 10; i++) {
vector.addElement(new Test(i, false));
System.out.println("add");
}
Enumeration en = vector.elements();
while (en.hasMoreElements()) {
Test tt = (Test)en.nextElement();
vector.remove(tt);
System.out.println("remove");
// en = vector.elements();
}
}}打开注释正常执行10次,关闭却只能执行5次,但是明明en里面还有5个对象,为什么此时执行hasMoreElements()判断却为false,十分不解。

解决方案 »

  1.   

    不清楚。感觉上en只是单纯的保存了vector随机访问时的下标i:
    1.hasMoreElements()是在比较en中保存的i与vector.size()
    2.nextElement()调用了vector.elementAt(i++)
    不知道上面的猜测对不对~~~
    建议楼主改用ArrayList和Iterator。用Iterator接口的remove方法来删除元素,这样就不会出错了。
      

  2.   

    额,elements()的源码:
        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 elementData(count++);
                        }
                    }
                    throw new NoSuchElementException("Vector Enumeration");
                }
            };
        }
      

  3.   

    简单起见,只举删除一个的例子
    原来你有10个元素,假设删除第9个
    此时Enumeration的计数器=8(第9个),删除一个,vector长度变为9,
    下一次hasMoreElements的时候,他用计数器和vector的当前长度比较,发现相同,自然返回false
      

  4.   

    如果要边遍历边删除,当然用Iterator
      

  5.   

    这本身是一个边遍历边删除的问题,楼主可以在这两行
    Test tt = (Test)en.nextElement();
      vector.remove(tt);中插入System.out.print(tt.i + " ");//结果是0 2 4 6 8
    因为nextElement()方法是返回当前地址中的元素,并指向下一个元素的地址,当你调用vector.remove(tt);时这时就会造成Vector底层数组所存储的对象引用的向前移动,而en所指向的地址并未发生变化,这就会形成1,3,5,7,9这些元素没有被遍历到的现象当你加上en = vector.elements();时就会造成en所指向的地址始终指向第一个元素所在的地址,
    又由于remove所引起的移动,则会出现这样的现象System.out.print(tt.i + " ");//结果是0 1 2 3 4 5 6 7 8 9
      

  6.   

    2楼的猜想很正确!将楼主的代码改为Iterator和ArrayList进行试验了一下我发下Iterator并不支持边遍历边删除(指的是删除ArrayList中的元素),可如果改为用3楼的Iterator的remove方法就不会出现错误,但这里调用的remove又有什么意义呢?而且删除的又是哪些元素?求指教
      

  7.   

    /**
         * 
         * Removes from the underlying collection the last element returned by the
         * iterator (optional operation).  This method can be called only once per
         * call to <tt>next</tt>.  The behavior of an iterator is unspecified if
         * the underlying collection is modified while the iteration is in
         * progress in any way other than by calling this method.
         *
    这里可不可以这样理解,remove删除的是Iterator所返回的元素(而这个元素只是Iterator的一个表象值),Iterator的引用同样是保存了Arraylist底层数组的下标;
      

  8.   

    二楼的猜想和我一开始解决这个问题的想法是一致的 en都是指向了Vector对象的引用查了一下api 发现remove的时候 元素都会向上相对移动一个位置 这样就相当于遍历跳过了下一个元素 这样始终都只会执行一半的元素遍历
    en = vector.elements(); 这个代码也是临时想到解决这个问题的 意义就不说了 很简单的重置一下指针到开头而已 对于使用iterator来代替的情况 不清楚iterator是否是线程安全的 在处理大数据量的遍历 vector 随即访问 效率比list高得多 而且是线程安全的 vector源码已经写明了 还有就是Enumeration的源码我找到的怎么都是抽象声明 在哪个地方有 谢谢!
      

  9.   


    源码在Vector类中的elements()中的匿名内部类里
      

  10.   

    刚查了下源码iterator list 这些在删除的时候不是线程安全的 所以这里用的vector
      

  11.   

    还有就我所知ArrayList和Iterator在线城方面好像不太安全
      

  12.   


    源码在Vector类中的elements()中的匿名内部类里
    谢谢 刚才在你说之前找到了 粗略看了下实现 十分感谢! 怎么今天傻逼了去看接口声明了 哈哈 
      

  13.   

    我看了源码 vector的方法 基本都是线程安全的 所以在处理删除这类业务的时候 选择vector是正确的 而且vector是随即访问 大数据的时候 效率比那些高 主要是自己写了个数据库连接池 用了下vector 连接池今天也写完美了 呵呵