java.util.Set什么时候检查重复项

时间:2012-05-30 10:51:53

标签: java set hashset

我有一个非常基本的问题,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);

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

w.r.t equals或hashcode是否发生了任何违规行为? 如果这段代码完全没问题,那么有什么方法可以防止添加重复项?

我假设,在确定equals和hashcode时使用的字段应该是immutabe吗?

2 个答案:

答案 0 :(得分:18)

  

我假设,在确定equals和hashcode时使用的字段应该是不可变的吗?

没错。

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

  

注意:如果将可变对象用作set元素,则必须非常小心。如果在对象是集合中的元素的同时以影响等于比较的方式更改对象的值,则不指定集合的​​行为。这种禁止的一个特例是,不允许集合将自己作为一个元素包含在内。

一旦违反合同,所有投注都将被取消。

答案 1 :(得分: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()方法返回相同的哈希码,那么它将使用object属性检查equals()方法并检查,是一些 对象属性的变化与否?根据结果​​,它将该对象存储在集合中,或者可能不存储。