如果不覆盖hashCode(),HashSet允许重复项目插入 [英] HashSet allows duplicate item insertion if hashCode() is not overridden

查看:74
本文介绍了如果不覆盖hashCode(),HashSet允许重复项目插入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class temp {
int id;

public int getId() {
  return id;
}

temp(int id) {
  this.id = id;
}

public void setId(int id) {
  this.id = id;
}

@Override
public boolean equals(Object obj) {
  if (this == obj)
      return true;
  if (obj == null)
      return false;
  if (getClass() != obj.getClass())
      return false;
  temp other = (temp) obj;
  if (id != other.id)
      return false;
  return true;
}
}

public class testClass {

    public static void main(String[] args) {
      temp t1 = new temp(1);
      temp t2 = new temp(1);
      System.out.println(t1.equals(t2));
      Set<temp> tempList = new HashSet<temp>(2);
      tempList.add(t1);
      tempList.add(t2);
      System.out.println(tempList);
}

程序将两个元素添加到Set中。我首先感到震惊,因为在添加方法时,调用了equals方法。

The program adds both the elements to the Set. I was shocked at first because while adding methods to set, equals method is invoked.

然后我覆盖了hashCode方法:

But then I overrode the hashCode method:

@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        return result;
    }

然后它没有添加。这是令人惊讶的,因为Set和add()方法的Javadoc说它在添加到Set时只检查equals()。

And then it did not add. This is surprising as the Javadoc of Set and add() method says that it checks only equals() while adding into the Set.

这是add的javadoc( ):

And this is the javadoc for add():

/**
     * Adds the specified element to this set if it is not already present.
     * More formally, adds the specified element <tt>e</tt> to this set if
     * this set contains no element <tt>e2</tt> such that
     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
     * If this set already contains the element, the call leaves the set
     * unchanged and returns <tt>false</tt>.
     *
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     * element
     */
    public boolean add(E e) {
      return map.put(e, PRESENT)==null;
    }

然后我意识到HashSet是作为HashMap实现的,在地图中,对象的hashCode用作键。因此,如果你不重写hashCode,它会使用不同的键来处理它们。

Then I realized that the HashSet is implemented as a HashMap and in the map, the hashCode of the object is used as the key. So, it is treating them using different keys if you dont override hashCode.

这不应该在add()方法或HashSet的文档中吗? / p>

Shouldn't this be in the documentation of the add() method or that of HashSet?

推荐答案

有点记录。请参阅 java.lang.Object 的文档,它在 hashCode()上显示

It kind of is documented. See the documentation for java.lang.Object, where it says on hashCode():


如果两个对象根据equals(Object)方法相等,然后
在两个对象中的每一个上调用 hashCode方法必须产生
相同的整数
结果。

If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

此外,在 Object.equals(对象)的文档中可以找到以下内容:方法:

Additionally the following is found in the documentation for the Object.equals(Object) method:


注意,一旦覆盖此方法,通常需要覆盖hashCode方法
,以便维护hashCode方法的一般
合约,其中声明相等对象必须
具有相等的哈希码

换句话说,如果你的班级是 instanceA.equals(instanceB)== true instanceA.hashCode()!= istanceB.hashCode()您实际上违反了Object类的合约。

In other words, if with your class when instanceA.equals(instanceB) == true and instanceA.hashCode() != istanceB.hashCode() you are in fact violating the contract of the Object class.

这篇关于如果不覆盖hashCode(),HashSet允许重复项目插入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆