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

如果仅在类中重写hashCode()并在Set中使用它,会发生什么情况?

咸弘雅
2023-03-14
问题内容

这可能不是现实情况,只是好奇地知道会发生什么,下面是代码

我正在创建一组class对象UsingSet。根据Java中的哈希概念,当我第一次添加包含“
a”的对象时,它将创建带有哈希码97的存储桶并将该对象放入其中。同样,当它遇到带有“
a”的对象时,它将在类UsingSet中调用覆盖的哈希码方法,并将获得哈希码97,那么下一步是什么?

由于我尚未重写equals方法,因此默认实现将返回false。那么,将具有哈希码97的先前对象保留在同一个存储桶中,将值“
a”的对象保留在何处?还是会创建新的存储桶?有人知道如何将其内部存储吗?

/* package whatever; // don't place package name! */

import java.util.*;
import java.lang.*;
import java.io.*;

class UsingSet {

  String value;

  public UsingSet(String value){  
    this.value = value;  
  }

  public String toString() {  
    return value;  
  }

  public int hashCode() {  
    int hash = value.hashCode();  
    System.out.println("hashcode called" + hash);  
    return hash;  
  }

  public static void main(String args[]) {

    java.util.Set s = new java.util.HashSet();

    s.add(new UsingSet("A"));  
    s.add(new UsingSet("b"));  
    s.add(new UsingSet("a"));  
    s.add(new UsingSet("b"));   
    s.add(new UsingSet("a"));

    s.add(new Integer(1));  
    s.add(new Integer(1));

    System.out.println("s = " + s);

  }  
}

输出为:

hashcode called65
hashcode called98
hashcode called97
hashcode called98
hashcode called97
s = [1, b, b, A, a, a]

问题答案:

James Large答案是错误的,或者是误导性的(部分错误也是如此)。我会解释。

如果两个对象根据其equals()方法相等,则它们还必须具有相同的哈希码。如果两个对象具有相同的哈希码,则它们也不必相等。

这是java.util.Object文档中的实际措辞:

  • 如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
    * 如果根据equals(java.lang.Object)方法,两个对象不相等,则不需要在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

的确,如果两个对象没有相同的哈希,那么它们将不相等。但是,哈希不是检查相等性的方法-因此说它是检查相等性的较快方法是非常不正确的。

同样,说hashCode函数是执行任何操作的有效方法,这也是非常不正确的。这完全取决于实现,但是随着String变大,字符串的hashCode的默认实现效率很低。它将基于String的每个字符执行计算,因此,如果您使用大型Strings作为键,则效率会非常低;此外,如果您有大量的存储桶。

在地图中(HashSet在内部使用HashMap),其中包含存储桶,并且每个存储桶中都有一个链表。Java使用hashCode()函数找出它属于哪个存储桶(它实际上将修改哈希,具体取决于存在的存储桶数量)。由于两个对象可能共享相同的哈希,因此接下来它将依次遍历链接列表,并检查equals()方法以查看该对象是否为重复对象。根据java.util.Set文档:

不包含重复元素的集合。

因此,如果其hashCode()将其引导到存储桶,该存储桶中包含一个.equals()计算为true的对象,则先前的对象将被新对象覆盖。您可能可以在此处查看更多信息:
JavaHashMap如何使用相同的哈希码处理不同的对象?

通常来说,优良作法是,如果覆盖hashCode函数,那么也将覆盖equals函数(如果我没记错的话,如果选择不这样做,就会违反合同)。



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

  • 问题内容: 在哈希图中,提供的键的哈希码用于将值放在哈希表中。在哈希集中,对象哈希码用于将值放置在基础哈希表中。即,哈希图的优点是您可以灵活地确定要作为密钥的内容,这样您就可以完成类似的事情。 这可以将诸如玩家名称之类的字符串映射到玩家本身。 我的问题是,当键的哈希码更改时,查找会发生什么情况。 我希望这不是Hashmap的主要关注点,因为我既不希望也不希望更改密钥。在前面的示例中,如果玩家名称更

  • Linux上的<code>int 0x80 64位代码应该使用< code>syscall,调用号来自< code >/usr/include/ASM/unistd _ 64 . h ,args在< code>rdi、< code>rsi等。了解UNIX的调用约定是什么 (有关 32 位与 64 位的示例,请参阅在 64 位 Linux 上使用中断0x80) 系统调用比 系统调用更快,因此请使用本

  • 问题内容: 因此,当我发现一些非常奇怪的东西时,我正在使用Node.js REPL和Underscore库。如果I ,则该变量是全局设置的(显然)。然后,当我尝试运行一个简单的命令时,它会打印出来(显然,再次)。但是,此后立即运行,因为变量设置为,它会打印。 为什么这样做呢?如果我从js文件运行相同的代码,则不会发生。这是正常的Node事情,还是全部错误? 仅供参考:节点v0.10.10 问题答案

  • 我用java编写Rational类来做基本的数学运算,我想覆盖Number类和Comparable接口的方法。我这样做是为了双倍的价值 正如我们所知,BigInteger类也扩展了数字类,所以我对在doubleValue中调用哪个方法感到困惑,因为我已经覆盖了doubleValue

  • 我在代码中使用了嵌套的Coroutine块。当我试图将Deferredtype的结果转换为变量时,得到了一个空值。因此,它导致了一个转换问题,即kotlin.TypeCastException:null不能转换为getNearbyHealthInstitutions()方法返回行中的非空类型kotlin.Collections.ArrayList。我相信,我在某个时候做了正确的实现,但是我错过了什