1、老师说删掉集合类中的元素用迭代器的remove方法安全,并用下面的程序给我们 做了演示 ,用集合类的remove方法确实删不掉kk.si这个元素,不过老师 也说不出 原理来,我想请问一下为什么会这样,而且换不同的Collection子类问题也不同,有的甚至运行时异常,这是为什么呢?
2、老师说要使c.remove(new Name("zhang", "san"));删掉zhang.san,必须在name类里重写equals方法和hashcode方法,重写 equals方法我明白是为了把比较引用改成比较内容,但重写的 hashcode的这个方法我还是不太明白!
import java.util.*;public class TestCollection { public static void main(String[] args) {
Collection c = new LinkedList(); c.add("123");
c.add(new Name("zhang", "san"));
c.add(new Name("ll", "si"));
c.add(new Name("kk", "si")); Iterator i = c.iterator();//迭代器
while (i.hasNext()) {
Object o =i.next();
if (o instanceof Name) {
Name n = (Name) o;//对象造型
if (n.getFirstName().length() < 3) {
System.out.println(n.getFirstName());
//i.remove();//Iterator对象的remove方法是在迭代过程中删除元素的唯一的安全方法
c.remove(n);//不安全 }
}
}

System.out.println(c.size());
System.out.println(c);
}
}class Name {
private String firstName;
private String lastName; public String getFirstName() {
return firstName;
} public String getLastName() {
return lastName;
} public Name(String f, String l) {
this.firstName = f;
this.lastName = l; } public String toString() {
return this.firstName + "." + this.lastName;
} public boolean equals(Object obj) {
if (obj instanceof Name) {
Name n = (Name) obj;
return this.firstName.equals(n.firstName)
&& this.lastName.equals(n.lastName);
}
return super.equals(obj); } public int hashCode() {
return this.firstName.hashCode()+this.lastName.hashCode();
}}

解决方案 »

  1.   

    你问的问题挺细的,看来是块搞技术的料。而且换不同的Collection子类问题也不同,有的甚至运行时异常,这是为什么呢?这是因为子类中的删除方法的具体实现不同。如果你想知道原因,你就去看jdk中的源码吧。
    必须在name类里重写equals方法和hashcode方法,重写 equals方法我明白是为了把比较引用改成比较内容,但重写的 hashcode的这个方法我还是不太明白! 这个跟删除没关系。我以前看到过这样的技术文章。但现在忘记了,我去查阅一下资料。再告诉你答案!
      

  2.   

    谢谢 您的解答
    1、目前我还不敢看jdk源码,呵呵 !因为基础知识还没学完呢,您看我目前记住这句话是不是对的------因为Collection具体子类的实现不同,所以使用迭代器的remove方法才能保证正确的结果。
    2、如果用c.remove(new Name("zhang", "san"));删除,是不是又在集合器外部新new了一个张三,jdk调用自定义name类的equals方法和hashcode方法,如果不重写,因为objiect的方法比较的是引用,引用不同,集合器判断不含此元素,所以删不掉,如果name类重写这2个方法,变成比较内容,集合器就会找到自己里面含有并删除,而集合器外面那个由垃圾回收机制处理,如果是这样的话,这个hashcode方法让我混乱,它返回的是集合器里面张三的hashcode还是集合器外面的那个张三的hashcode,什么是hashcode?我的理解是标识身份的一个int值,不过这个hashcode有什么用?好像只重写equals就行了吧?混乱中......
      

  3.   

    你用的collection对象删除其中的一个元素后,collection内的元素就会少一个,当把ll删除后,ss自动替换了ll的位置,在i.hasNext时就到了collection的末尾,所有推出了循环,你可以用i.remove()方法来删除
    Iterator i = c.iterator();//迭代器
            while (i.hasNext()) {
                Object o = i.next();
                if (o instanceof Name) {
                    Name n = (Name) o;//对象造型
                    if (n.getFirstName().length() < 3) {
                        System.out.println("n.getFirstName()"+n.getFirstName());
    //i.remove();//Iterator对象的remove方法是在迭代过程中删除元素的唯一的安全方法
                        //c.remove(n);//不安全
                        i.remove(); //改成用i.remove()方法删除
                    }
                }
            }
      

  4.   

    噢,这是集合类的特性造成的,这么说如果用i.remove();就算collection自动紧缩,改变其后元素的索引值,
    迭代器也能正确的找到真正的那个next?
      

  5.   

    大家好,我是一名JAVA初学者,确实我也觉得只重写equals方法就行了 我想的和楼主的差不多,不过我想对于hashcode(),只要是引用的对象(如此时的Name)重载了相应的hashcode(),那么不同引用(对同一个对象)调用hashcode()就应该生成同样的值。否则就是不同的hashcode.故而如果此时你只重载equals而不重载hashcode的话,那么我估计当你引用c.remove(new Name("zhang", "san"))删除的时候只是删除你在堆中刚新建的“zhang”对象(虽然此时有2个内容一样的Name对象,一个在C中,一个在堆另外的一块存储空间中,此时删除hashcode就起了重要作用,是编译器能够正确识别的依据),而原来C中的zhang对象仍然没删除。
    我也不知道分析的对不对,这当中我也有很多模糊的地方,看来要看看书啦。
      

  6.   

    如果只重写equals,也能删除
    import java.util.*;public class TestCollection { public static void main(String[] args) {
    Collection c = new LinkedList(); c.add("123");
    c.add(new Name("zhang", "san"));
    System.out.println(c); c.remove(new Name("zhang", "san"));

    System.out.println(c);
    }
    }class Name {
    private String firstName;
    private String lastName; public Name(String f, String l) {
    this.firstName = f;
    this.lastName = l; } public String toString() {
    return this.firstName + "." + this.lastName;
    } public boolean equals(Object obj) {
    if (obj instanceof Name) {
    Name n = (Name) obj;
    return this.firstName.equals(n.firstName)
    && this.lastName.equals(n.lastName);
    }
    return super.equals(obj); } //public int hashCode() {
    //return this.firstName.hashCode()+this.lastName.hashCode();
    //}}
      

  7.   

    在网上搜了点资料,加上我反复测试之后,我终于弄明白了,各位:这有点编译时多态的味道,LinkedList根本 不会调用hashcode方法,所以hashcode重不重写根本就无所谓,但是有的容器会调用hashcode方法,所以equals和hashcode都重写,保险点