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呢 。
- OK,最后啊,这hashcode()方法到底应该怎么写呢,这也头大啊 , 一个hashcode()咋就那么难呢,来来来思考两分钟,你想好怎么写了嘛 。先别说 , 我把前提撩在这,你在仔细想想 。一个是 ”相同的对象“ 的 hashcode() 要相同,不同对象的 hashcode() 不能相同 。比如 :
Person key = new Person("1","张三");Person sameKey = new Person("1","张三");Person unSameKey = new Person("2","张三");
其中 key 和 sameKey 的 hashcode()一定要相同,因为我们的业务员就是认为他们应该是相同的 。但是同时 unSame 和 key 的 hashcode() 一定不能相同 。
- 这个时候,使用Object的 hashcode() 很显然就是不行了,应为它返回每个对象的 hashcode() 都是不相同的 。
- 当然了 , 所有 hashcode() 都返回 0,这也不是不行,只是违背了这句话:如果两个对象hashCode相同 , 不能证明两个对象是同一个对象(不一定相等) 。
来吧,开始发散思维 。方法一:
- 使用String 的hashcode(),你对象里面的属性不是String 类型嘛,String 里面已经重写了 hashcod() 方法那我直接用现成的就好了 。
@Overridepublic int hashCode() {returnid.hashCode() + name.hashCode();}
但是我们还是要从各个角度出发去想一下的,比如判空,是否会值溢出之类的,这里我们也参考String 的 hashcode() 套娃一个 。优化后:
@Overridepublic int hashCode() {//初始值 , 别问为什么是 17, 因为我写 18 你也会这样问的int result = 17;// 31 作为基数,不知道啊,String 里面 的 hashcode() 就是写的 31result = 31 * result + (id == null ? 0 : id.hashCode());result = 31 * result + (name == null ? 0 : name.hashCode());return result;}
方法二:- 调用JDK提供好的Objects里面的hashcode()
@Overridepublic int hashCode() {return Objects.hash(id,name);}
看了这两个方法,没错,这都是站在巨人的肩膀上 。其实要是自己动手实现,那难度就直线上升了,至少算法这一块要啃一下 。hashcode() 方重写规则
写hashcode()要遵循以下原则:知识盲区
equals不相等时并不强制要求哈希值相等 , 但是一个优秀的哈希算法应尽可能让元素均匀分布,降低冲突发生的概率,即在equals不相等时尽量让哈希值也不相等,这样&&或||短路操作一旦生效,会极大提高程序的效率 。
重写equals都是根据业务需求去进行重写的,想想为什么String是这么判断两个字符串对象相等的 。如果抛开业务需求谈这个,就是耍流氓 。但是大多数情况下,都是不用重写 equals() 和 hashcode() 的,就是因为有了特殊的业务逻辑,所以我们才需要重写里面的逻辑 。
推荐阅读
- 真我gtneo2续航表现_真我gtneo2续航测试
- 真我x7pro至尊版值得买吗_真我x7pro至尊版值得入手吗
- 真我gt2pro和小米12pro哪个好-真我gt2pro和小米12pro参数对比
- BLS签名算法
- WOW真银矿哪里多啊 银矿在哪里
- @Transactional注解真的有必要声明rollbackFor属性吗?
- realme真我Q3s评测_realme真我Q3s全面评测
- 求笔仙的玩法真实的(亲身体验笔仙)
- 笔仙怎么玩啊,玩了有后果吗,真的有笔仙吗
- 真我GT Neo2和大师探索版哪个好_怎么选择