12

我有一个非常基本的问题,java.util.Set 何时检查添加的对象是否重复?

因为我有一个模型类如下,它覆盖了equals和hashcode方法

public class SampleModel implements Comparable {
    private String name;

    public SampleModel(String name) {
        this.name = name;
    }

    // Setter and Getter omitted
    @Override
    public boolean equals(Object arg0) {
        boolean eq = false;

        if (arg0 instanceof SampleModel
                && this.name.equalsIgnoreCase(((SampleModel) arg0).name)) {
            eq = true;
        }
        return eq;
    }

    @Override
    public int compareTo(Object arg0) {
        return this.name.compareTo(((SampleModel) arg0).name);
    }

    @Override
    public int hashCode() {
        return this.name.length();
    }
}

然后这就是我在 HashSet 中使用模型对象的方式。

    SampleModel s1 = new SampleModel("Satya");
    SampleModel s2 = new SampleModel("Katti");

    Set<SampleModel> samSet = new HashSet<SampleModel>();
    System.out.println(samSet.add(s1));
    System.out.println(samSet.add(s2));

    s2.setName("Satya");
    System.out.println(s2.getName());
    System.out.println(s1 + ", " + s2);

根据相等子句,对象相同且相等,但 HashSet 将包含重复项。

是否有任何违规发生在等于或哈希码上?如果这段代码完全没问题,那么有什么方法可以防止添加重复项?

我假设,用于确定 equals 和 hashcode 的任何字段都应该是不可变的?

4

2 回答 2

18

我假设,用于确定 equals 和 hashcode 的任何字段都应该是不可变的?

这是正确的。

更准确地说,您问题中的代码违反了Set合同的以下部分:

注意:如果将可变对象用作集合元素,则必须非常小心。如果对象的值以影响等于比较的方式更改,而对象是集合中的一个元素,则不指定集合的​​行为。此禁令的一个特殊情况是不允许集合包含自身作为元素。

一旦您违反合同,所有赌注都将取消。

于 2012-05-30T10:55:08.860 回答
0

要理解的示例:

import java.util.*;

public class Vector1{

  public static void main(String args[]){


    Set v=new HashSet();
    Student st=new Student("12","naushad");
    Student st1=new Student("12","naushad");
    v.add(st1);
    v.add(st);
    System.out.println(st.hashCode());
    st.sname="shouzia";
    System.out.println(st.hashCode());

    v.add(st);
    v.add(st);
    v.add("naushad");
    v.add("naushad");
    v.add("naushad");

    System.out.println(v);
    }

}

class Student{

    public String sid;
    public String sname;

    Student(String sid,String sname){
        this.sid=sid;
        this.sname=sname;
    }

    public String toString(){

        return sid+"\t"+sname;
    }

}

我已经用相同的数据实例化了两个对象,它将存储在 Set 中,因为它们都包含不同的哈希码,所以这里不需要比较 equals() 方法。

如果 hashcode() 方法返回相同的哈希码,那么它将检查 equals() 方法与对象属性并检查对象属性是否发生了一些变化?根据结果​​,它将将该对象存储在集合中,也可能不存储。

于 2014-09-08T14:07:31.913 回答