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

等于和hashCode:Objects.hash方法是否损坏?

桑成荫
2023-03-14
问题内容

我正在使用Java
7,下面有下面的类。我实现equalshashCode正确的,但问题是,equals收益false的主要方法,下面又hashCode返回两个对象相同的散列码。我可以让更多的眼睛看着这个班级,看看我在这里做错了什么吗?

更新: 我更换了我称之为行Objects.hash方法用我自己的哈希函数:chamorro.hashCode() + english.hashCode() + notes.hashCode()。它返回一个不同的哈希码,这是hashCode当两个对象不同时应该执行的操作。是Objects.hash方法打破?

对你的帮助表示感谢!

import org.apache.commons.lang3.StringEscapeUtils;

public class ChamorroEntry {

  private String chamorro, english, notes;

  public ChamorroEntry(String chamorro, String english, String notes) {
    this.chamorro = StringEscapeUtils.unescapeHtml4(chamorro.trim());
    this.english = StringEscapeUtils.unescapeHtml4(english.trim());
    this.notes = notes.trim();
  }

  @Override
  public boolean equals(Object object) {
    if (!(object instanceof ChamorroEntry)) {
      return false;
    }
    if (this == object) {
      return true;
    }
    ChamorroEntry entry = (ChamorroEntry) object;
    return chamorro.equals(entry.chamorro) && english.equals(entry.english)
        && notes.equals(entry.notes);
  }

  @Override
  public int hashCode() {
    return java.util.Objects.hash(chamorro, english, notes);
  }

  public static void main(String... args) {
    ChamorroEntry entry1 = new ChamorroEntry("Åguigan", "Second island south of Saipan. Åguihan.", "");
    ChamorroEntry entry2 = new ChamorroEntry("Åguihan", "Second island south of Saipan. Åguigan.", "");
    System.err.println(entry1.equals(entry2)); // returns false
    System.err.println(entry1.hashCode() + "\n" + entry2.hashCode()); // returns same hash code!
  }
}

问题答案:

实际上,您碰巧触发了纯粹的巧合。:)

Objects.hash碰巧是通过相继添加每个给定对象的哈希码,然后将结果乘以31来实现的,而String.hashCode对每个字符都执行相同的操作。碰巧的是,您所使用的“英语”字符串中的差异与字符串末尾的偏移量恰好比“
Chamorro”字符串中的差异大了一个偏移量,因此所有内容都可以完美抵消。恭喜你!

尝试其他字符串,您可能会发现它可以按预期工作。正如其他人已经指出的那样,严格来说,这种效果实际上并没有错,因为即使哈希码表示的对象不相等,哈希码也可能正确冲突。如果有的话,尝试找到一个更有效的哈希值可能是值得的,但我认为在现实情况下几乎没有必要。



 类似资料:
  • 问题内容: 我将某些本机方法重写为常规Java方法。 本机方法有效地静态吗?或者是否曾经有一个隐式的“ this”参数? 谢谢! 问题答案: 就像常规Java方法一样,本机方法可以是非方法。 非本机方法接收引用,而非本机方法则接收对containg类的引用。 根据JNI规范: 本机方法参数 JNI接口指针是本机方法的第一个参数。JNI接口指针的类型为JNIEnv。第二个参数根据本机方法是静态还是静

  • 问题内容: public class TestMain { 输出:NullPointerException方法调用 问题答案: 如果有多个重载方法可以使用给定的参数调用(在您的情况下),则编译器将选择最具体的方法。 参见http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.5 您的情况比更为具体,因为Exc

  • 问题内容: 有些人认为这样做存在一些缺陷,即使正确使用也无法保护您的查询。 带一些化石的物品作为证明。 因此,问题是:mysql [i] _real escape_string()完全不可接受吗? 还是仍然可以使用此功能来创建自己的预备语句? 请提供校对码。 问题答案: 从MySQL的C API函数描述 : 如果需要更改连接的字符集,则应使用函数而不是执行(或)语句。的工作方式类似,但也会影响所使

  • 问题内容: 显然,这比我想象的要难找到。而且甚至很简单… 是否有与Javascript中内置的PHP htmlspecialchars等效的功能?我知道自己很容易实现,但是使用内置函数(如果可用)会更好。 对于不熟悉PHP的人,htmlspecialchars可将类似的内容转换为 我知道这一点,因此不能这样工作。 问题答案: 解决方案代码存在问题-它只会转义每个特殊字符的第一次出现。例如: 这是正

  • 问题内容: 我正在配置Java客户端,它的工作是建立与服务器的TLS连接。我想使用以下3种密码配置客户端: 在Java支持的密码套件中,我找到了相同的密码,但是开头是SSL,而不是TLS。问题是,如果我用以下方法配置了客户端: 这两个列表是否完全相同,并且服务器将对其进行解释?我担心是否为客户端配置了密码,这意味着与某些不同,并且可能某些服务器不支持。我如何确定? 问题答案: 是的,它们是相同的。

  • 问题是: 我们将“根到叶路径”定义为树中的任意节点序列,从根节点开始向下延伸到叶。该路径的“根到叶路径和”是沿该路径的所有节点(包括根)的和。定义一个空树,使其不包含根到叶的路径(因此其和为零)。定义一个具有一个节点的树,使其根到叶的路径仅由根组成(因此其总和是根的值)。给定一个二叉树和一个值“sum”,如果该树有一些根到叶的路径,使得沿路径的所有值相加等于“sum”,则返回true。如果找不到这