简体   繁体   English

String的hashCode与其他类对象的比较

[英]The hashCode for String versus other class objects

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");
    }
  }
}

Question/Confusion: The default hashCode for Object class seems to be taking into consideration the object reference and not just the contents, why else would the employee class object with the same name be coming out with a different hash code? 问题/困惑: Object类的默认hashCode似乎在考虑对象引用,而不仅仅是内容,为什么同名员工类对象会以不同的哈希码出现? If the default implementation of Object class had some hash algorithm based on contents alone, there would not be such a need to override the hashCode method as long as my equals paradigm agrees with the bitwise compatibility. 如果Object类的默认实现仅具有基于内容的某种哈希算法,则只要我的equals范式与按位兼容,就不需要重写hashCode方法。

Anything to clear this confusion? 有什么可以清除这种混乱的地方吗?

The default hashCode() is not based on the reference, nor any address in the system. 默认的hashCode() 既不基于引用,也不基于系统中的任何地址。 It is a randomly generated number stored in the header. 它是存储在标头中的随机生成的数字。 It does this so the object can be moved without changing the hashCode() and the hashCode is reasonably random. 这样做是为了可以在不更改hashCode()的情况下移动对象,并且hashCode是相当随机的。

Note: 注意:

  • after a minor GC, the eden space is empty and the first object created is always at the same address. 在次要GC之后,eden空间为空,并且创建的第一个对象始终位于同一地址。 It doesn't have the same hashCode. 它没有相同的hashCode。
  • object are created on 8-byte boundaries by default, so the lower three bit can be all 000 which is not useful for a hashCode. 默认情况下,对象是在8字节边界上创建的,因此低三位可以全部为000,这对于hashCode无效。 If you use Compressed Oops, the lower bits might not be stored, but is still not very random. 如果使用Compressed Oops,则可能不会存储低位,但仍然不是很随机。
  • Using Unsafe you can read and even overwrite the stored hashCode. 使用Unsafe您可以读取甚至覆盖存储的hashCode。 On the OracleJVM/OpenJDK, the hashCode is stored 1 byte from the start of the object. 在OracleJVM / OpenJDK上,hashCode从对象的开头开始存储1个字节。
  • The bits used to store the hashCode is also used for baised locking. 用于存储hashCode的位也用于平衡锁定。 Once you obtain the builtin hashCode for an object, it will not use biased locking. 一旦获取了对象的内置hashCode,它将不会使用有偏锁。
  • you can obtain the system hashCode of any object using System.identityHashCode(x) which is what IdentityMap uses. 您可以使用IdentityMap使用的System.identityHashCode(x)获得任何对象的系统hashCode。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM