JavaSE---hash与Object.hashCode()
总结
hashcode解决什么问题?
1、集合的高效插入、删除、查找
通过hashcode()计算出的值,可以快速 定位元素存储的位置
2、哈希表结构的高效查找
通过hashcode()计算出的值,可以快速 定位元素存储的位置
System.identityHashCode和Object.hashCode()
都可以用于获取对象的哈希码,但是它们之间有一些重要的区别。
Object.hashCode():
这个方法可以被子类覆盖(override),这意味着如果你使用的是一个自定义的对象,并且该对象的类重写了 hashCode 方法,那么调用 hashCode 会返回根据该类逻辑计算出的哈希码。这通常是基于对象的内容(即字段值)来计算的。
如果没有被覆盖,Object.hashCode() 和 System.identityHashCode(Object x) 对于同一个对象通常会返回相同的值;
System.identityHashCode(Object x):
这个方法不会被任何类的方法覆盖。它总是返回与对象的身份相关的哈希码,而不是内容。即使对象的 hashCode 方法被覆盖了,仍然会提供一个基于对象内存地址等底层信息的唯一标识符。
/** * <Hash/散列函数> * what * 把任意长度的输入 通过散列算法 变换成固定长度的输出,该输出就是散列值; * 这种转换是一种压缩映射(散列值的空间通常远小于输入的空间); * 不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值; * * (一种将任意长度的消息压缩到某一固定长度的消息摘要的函数) * * 特点 * 单向,不能反算; * * 应用 * 加密 (md5+salt) */
/** * <Object.hashCode()> * what * Returns a hash code value for the object. 返回一个对象的hash code值; * This method is supported for the benefit of hash tables such as those provided by java.util.HashMap. 在哈希表中的java.util.HashMap有使用到hashCode方法; * * Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. * 在一个Java应用程序的执行过程中,无论在同一个对象上多次调用hashCode方法时,只要没有修改对象上的equals比较中使用的信息,hashCode方法必须始终返回相同的整数。 * This integer need not remain consistent from one execution of an application to another execution of the same application. * 在不同的Java应用中,同一个对象的hashCode值没必要一致; * * If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result. * ***如果2个对象 通过equals方法 返回true,这2个对象的hashCode方法 应该返回相同的int值; * * It is not required that if two objects are unequal according to the java.lang.Object#equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. * 如果2个对象 通过equals方法 返回false,这2个对象的hashCode方法 应该返回不同的int值; * * However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables. * 程序员 应该意识到 "不同对象生成不同的hash code值会提升哈希表的性能"; * * 作用 * 用于 哈希表的 查找 * (直接计算要查找内容的hashCode值,hashCode值就是 哈希表的下标索引) * * 存储位置 * 对象头的MarkWord中 * * <hashCode与内存地址的关系> * https://www.cnblogs.com/javastack/p/15441274.html * * 1、Hotspot hashCode实现:hotspot/src/share/vm/runtime/synchronizer.cpp * 0:随机数 * 1:根据 对象内存地址 + 随机数 生成 * 2:固定值1 * 3:自增序列生成 * 4:对象内存地址 * else:xor-shift 生成 * * static inline intptr_t get_next_hash(Thread * Self, oop obj) { * intptr_t value = 0 ; * if (hashCode == 0) { * // This form uses an unguarded global Park-Miller RNG, * // so it's possible for two threads to race and generate the same RNG. * // On MP system we'll have lots of RW access to a global, so the * // mechanism induces lots of coherency traffic. * value = os::random() ; * } else * if (hashCode == 1) { * // This variation has the property of being stable (idempotent) * // between STW operations. This can be useful in some of the 1-0 * // synchronization schemes. * intptr_t addrBits = cast_from_oop<intptr_t>(obj) >> 3 ; * value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ; * } else * if (hashCode == 2) { * value = 1 ; // for sensitivity testing * } else * if (hashCode == 3) { * value = ++GVars.hcSequence ; * } else * if (hashCode == 4) { * value = cast_from_oop<intptr_t>(obj) ; * } else { * // Marsaglia's xor-shift scheme with thread-specific state * // This is probably the best overall implementation -- we'll * // likely make this the default in future releases. * unsigned t = Self->_hashStateX ; * t ^= (t << 11) ; * Self->_hashStateX = Self->_hashStateY ; * Self->_hashStateY = Self->_hashStateZ ; * Self->_hashStateZ = Self->_hashStateW ; * unsigned v = Self->_hashStateW ; * v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ; * Self->_hashStateW = v ; * value = v ; * } * * value &= markOopDesc::hash_mask; * if (value == 0) value = 0xBAD ; * assert (value != markOopDesc::no_hash, "invariant") ; * TEVENT (hashCode: GENERATE) ; * return value; * } * * */