【问题标题】:When does java.util.Set check for duplicatesjava.util.Set 何时检查重复项
【发布时间】:2012-06-04 14:26:50
【问题描述】:

我有一个非常基本的问题,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 将包含重复项。

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

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

【问题讨论】:

    标签: java set hashset


    【解决方案1】:

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

    没错。

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

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

    一旦你违反合同,所有的赌注都被取消了。

    【讨论】:

    • 也就是说,重复检查发生在调用add 期间,如the Javadoc 中所指定。 add(e) 如果 e 尚未在集合中并已被添加,则返回 true,如果已在集合中,则返回 false
    【解决方案2】:

    理解示例:

    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 中,因为两者 包含不同的hashcode,所以这里不需要比较 equals() 方法。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-16
      • 2016-10-12
      • 2015-07-14
      相关资源
      最近更新 更多