字符串与其他类对象的哈希码


class Employee {
  String name;
  Employee(String name) {
    this.name = name;
  }
  // hashCode method is not overridden
}
public class HashCodeConfusion {
  public static void main(String[] args) {
    Employee emp = new Employee("ABC");
    Employee emp1 = new Employee("ABC");
    if (emp == emp1) {
      System.out.println("Employee Same reference");
    } else {
      System.out.println("Employee Different reference");
    }
    if (emp.hashCode() == emp1.hashCode()) {
      System.out.println("Employee Same hash code");
    } else {
      System.out.println("Employee Different hash code");
    }
    // -----------------------------------
    String str = new String("ABC");
    String str1 = new String("ABC");
    if (str == str1) {
      System.out.println("String Same reference");
    } else {
      System.out.println("String Different reference");
    }
    if (str.hashCode() == str1.hashCode()) {
      System.out.println("String Same hash code");
    } else {
      System.out.println("String Different hash code");
    }
  }
}

问题/混乱:对象类的默认哈希码似乎正在考虑对象引用,而不仅仅是内容,为什么具有相同名称的员工类对象会带有不同的哈希代码?如果仅基于内容的对象类的默认实现具有某些哈希算法,那么只要我的等价范式与位兼容性一致,就不需要覆盖哈希码方法。

什么要清除这种混乱?

默认hashcode()不是基于参考的,也不基于系统中的任何地址。它是存储在标题中的随机生成的数字。它可以这样做,以便可以在不更改hashCode()的情况下移动对象,并且哈希码是合理的随机。

注意:

  • 次要GC后,伊甸园空间为空,而创建的第一个对象始终处于同一地址。它没有相同的哈希码。
  • 默认情况下在8字节边界上创建对象,因此下三位可以是所有000,这对hashcode没有用。如果您使用压缩的OOPS,则可能不会存储较低的位,但仍然不是很随机。
  • 使用Unsafe,您可以读取甚至覆盖存储的标签。在OracleJVM/OpenJDK上,从对象的开头存储了1个字节。
  • 用于存储HashCode的位也用于baised锁定。一旦您获得了一个对象的内置哈希码,它就不会使用偏置锁定。
  • 您可以使用IdentityMap使用的System.identityHashCode(x)获得任何对象的系统哈希码。

相关内容

  • 没有找到相关文章

最新更新