重写 hashcode真有那么简单嘛?( 三 )

hashcode() 真源码

  • 在openjdk8根路径/hotspot/src/share/vm/runtime路径下的synchronizer.cpp文件中,有生成哈希值的代码:
static inline intptr_t get_next_hash(Thread * Self, oop obj) {intptr_t value = https://www.huyubaike.com/biancheng/0 ;if (hashCode == 0) {// 返回随机数value = os::random() ;} elseif (hashCode == 1) {//用对象的内存地址根据某种算法进行计算intptr_t addrBits = cast_from_oop(obj) >> 3 ;value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;} elseif (hashCode == 2) {// 始终返回1 , 用于测试value = 1 ;} elseif (hashCode == 3) {//从0开始计算哈希值value = ++GVars.hcSequence ;} elseif (hashCode == 4) {//输出对象的内存地址value = cast_from_oop(obj) ;} else {// 默认的hashCode生成算法 , 利用xor-shift算法产生伪随机数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;}先上一首凉凉 。不是看不懂啊 , 毕竟大学学过C , 但是脑瓜子嗡嗡的 , 肯定不能专研这个了 , 先跳过 , 回到正题 。
为什么要重写hashcode我们大概知道了 , 那如果我偏不重写呢 , 先来个铁头娃demo看看效果 。
public class Person {//用户Id , 唯一确定用户private String id;private String name;public Person(String id, String name) {this.id = id;this.name = name;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (!(o instanceof Person)) return false;Person person = (Person) o;return Objects.equals(id, person.id) && Objects.equals(name, person.name);}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}@Testpublic void test() {HashMap<Person, Integer> map = new HashMap<>();//key:Person类型value:Integer类型Person personKey = new Person("1","张三");Person getKey = new Person("1","张三");map.put(personKey,100);System.out.println("原对象map.get():"+map.get(personKey));System.out.println("值相同的对象map.get():"+map.get(getKey));}输出结果:
-------测试前准备-创建对象-------原对象map.get():100值相同的对象map.get():null-------测试结束-------
这里我们很明显看到 , 我们要用之前的对象才能从HashMap中获取到key 。这不是我们想要的效果啊 , 再也不头铁了 。
  • 这时有人就会说了 , 那我用之前的对象不就好了嘛 , 干嘛要new个新的对象呢?其实这也是demo和实际项目的差距 。如果你做过项目的就知道 , 我们的实体类每次请求进来都是个新的对象 , 最最最不济 , 你什么PO转DO , DO转DTO不就是要创建新的对象嘛 。
呐呐呐 , 问题又来了 , 我不用Map不就行了 , 可以 。当然可以 , 但是现在的项目里面 , 如果说整个项目没有用到Map的 , 那这个项目估计也不叫项目了 , 写java的人 , 谁能拒绝来个Map呢 。