当前位置: 首页 > 面试题库 >

如果未覆盖hashCode(),则HashSet允许重复项插入

濮阳君浩
2023-03-14
问题内容
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);
}

该程序将两个元素都添加到集合中。起初我很震惊,因为在添加设置方法时,调用了equals方法。

但是后来我覆盖了hashCode方法:

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

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

这是add()的javadoc:

/**
     * 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,它将使用不同的键来对待它们。

这不是在add()方法的文档中还是在HashSet的文档中?


问题答案:

有记载。请参阅java.lang.Object的文档,该文档中的内容hashCode()如下:

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

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

请注意,通常有必要在每次重写此方法时都重写hashCode方法,以维护hashCode方法的常规约定,该约定规定 相等的对象必须具有相等的哈希码

换句话说,如果与您的类在何时instanceA.equals(instanceB) == trueinstanceA.hashCode() != istanceB.hashCode()实际上违反了Object类的约定。



 类似资料:
  • 该程序将两个元素都添加到Set中。起初我很震惊,因为在向set添加方法时,调用了equals方法。 但是后来我覆盖了hashCode方法: 然后它没有添加。这是令人惊讶的,因为Set和add()方法的Javadoc表示,它在向集合中添加时只检查equals()。 这是add()的javadoc: 然后我意识到HashSet被实现为一个HashMap,在这个map中,对象的hashCode被用作键。

  • 问题内容: 我似乎无法使实例正常工作。我使用的代码如下: 子类 该代码输出 问题答案: 您需要覆盖。而不是这样做,您实现了一个带有signature 的方法。因此,您使用的是为相等性测试定义的默认方法。 默认实现基于对象标识,因此,该集合“允许”您添加两个在语义上相等的不同对象。

  • 我正在检查< code>HashSet的< code>add方法。有人提到 如果该集合已经包含元素,则调用保持集合不变,并返回false。 但是方法在内部保存中的值 的方法声明 将指定值与该映射中的指定键相关联。如果映射先前包含该键的映射,则旧值将被替换。 那么,如果 的 方法替换了旧值,那么 方法如何在元素重复的情况下保持集合不变?

  • 我试图覆盖提到的方法为我的: MyObject: 如何重写hashcode(),equals()和compareTo()方法? 目前我有以下几点: 我读到通过id比较是不够的,这是对象是数据库的持久实体(见这里)。 此类型的所有对象的名称和编号不是唯一的。 那么我应该如何覆盖它呢? 我还需要比较它里面的hashMap吗? 我很困惑。该对象唯一独特的地方是map myMap,它将在生命周期的后期填充

  • 问题内容: 假设我创建了一个对象,该对象具有ID,firstName,lastName和email,用于实例变量和相应的setter / getter方法。如何,如果我不重写计算中时,它存储在集合对象的对象? 问题答案: 如果不重写hashcode(),则集合将使用Object类中的默认实现。即使根据equals()方法它们相等,此实现也会为不同的对象提供不同的值。 一些集合(例如HashSet,

  • 问题内容: 如果未重写hashCode()方法,那么对Java中的任何对象调用hashCode()的结果是什么? 问题答案: 在HotSpot JVM中,默认情况下会在第一次调用时生成未重载或随机数并将其存储在对象标头中。随后的调用或仅从标头中提取此值。默认情况下,它与对象内容或对象位置没有共同点,只有随机数。此行为由HotSpot JVM选项控制,该选项具有以下可能的值: 0:使用全局随机数发生