摘要:上面的程序输出的结果是两个。使用包重写和方法包提供了两个非常优秀的类来生成和方法。需要注意记住的事情尽量保证使用对象的同一个属性来生成和两个方法。方法必须保证一致如果对象没有被修改,应该返回相同的值任何时候只要那么必须和相等。
hashCode()方法被用来获取给定对象的唯一整数,这个整数被用来确定对象被存储在HashTable类似的结构中的位置,Object类的hashCode()方法返回这个对象存储的内存地址的编号。
equal()相等的两个对象他们的hashCode()肯定相等 hashCode()相等的两个对象他们的equal()不一定相等
对比的时候
首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等 如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了
这样的好处
hash散列算法,使得在hash表中查找一个记录速度变O(1).每个记录都有自己的hashcode,散列算法按照hashcode把记录放置在合适的位置.在查找一个记录,首先先通过hashcode快速定位记录的位置.然后再通过equals来比较是否相等.没有hashcode,一个一个比较过来,时间就变O(N)了
这种大量的并且快速的对象对比一般使用的hash容器中,比如hashset,hashmap,hashtable等等,比如hashset里要求对象不能重复,则他内部必然要对添加进去的每个对象进行对比,而他的对比规则就是像上面说的那样,先hashCode(),如果hashCode()相同,再用equal()验证,如果hashCode()都不同,则肯定不同,这样对比的效率就很高了
然而hashCode()和equal()一样都是基本类Object里的方法,而和equal()一样,Object里hashCode()里面只是返回当前对象的地址,如果是这样的话,那么我们相同的一个类,new两个对象,由于他们在内存里的地址不同,则他们的hashCode()不同,所以这显然不是我们想要的,所以我们必须重写我们类的hashCode()方法
public class Employee { private Integer id; private String firstname; private String lastName; private String department; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } } public class EqualsTest { public static void main(String[] args) { Employee e1 = new Employee(); Employee e2 = new Employee(); e1.setId(100); e2.setId(100); //Prints false in console System.out.println(e1.equals(e2)); } }
毫无疑问,上面的程序将输出false
我们需要重写equals方法
public boolean equals(Object o) { if(o == null) { return false; } if (o == this) { return true; } if (getClass() != o.getClass()) { return false; } Employee e = (Employee) o; return (this.getId() == e.getId()); }
在上面的类中添加这个方法,EauqlsTest将会输出true。
import java.util.HashSet; import java.util.Set; public class EqualsTest { public static void main(String[] args) { Employee e1 = new Employee(); Employee e2 = new Employee(); e1.setId(100); e2.setId(100); //Prints "true" System.out.println(e1.equals(e2)); Setemployees = new HashSet (); employees.add(e1); employees.add(e2); //Prints two objects System.out.println(employees); } }
上面的程序输出的结果是两个。如果两个employee对象equals返回true,Set中应该只存储一个对象才对,问题在哪里呢?
我们忘掉了第二个重要的方法hashCode()。就像JDK的Javadoc中所说的一样,如果重写equals()方法必须要重写hashCode()方法。我们加上下面这个方法,程序将执行正确。
@Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + getId(); return result; }
使用Apache Commons Lang包重写hashCode() 和equals()方法
Apache Commons 包提供了两个非常优秀的类来生成hashCode()和equals()方法。看下面的程序。
import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; public class Employee { private Integer id; private String firstname; private String lastName; private String department; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } @Override public int hashCode() { final int PRIME = 31; return new HashCodeBuilder(getId()%2==0?getId()+1:getId(), PRIME). toHashCode(); } @Override public boolean equals(Object o) { if (o == null) return false; if (o == this) return true; if (o.getClass() != getClass()) return false; Employee e = (Employee) o; return new EqualsBuilder(). append(getId(), e.getId()). isEquals(); } }
如果你使用Eclipse或者其他的IDE,IDE也可能会提供生成良好的hashCode()方法和equals()方法。
需要注意记住的事情
尽量保证使用对象的同一个属性来生成hashCode()和equals()两个方法。在我们的案例中,我们使用员工id。
eqauls方法必须保证一致(如果对象没有被修改,equals应该返回相同的值)
任何时候只要a.equals(b),那么a.hashCode()必须和b.hashCode()相等。
两者必须同时重写。
当使用ORM的时候特别要注意的
如果你使用ORM处理一些对象的话,你要确保在hashCode()和equals()对象中使用getter和setter而不是直接引用成员变量。因为在ORM中有的时候成员变量会被延时加载,这些变量只有当getter方法被调用的时候才真正可用。
例如在我们的例子中,如果我们使用e1.id == e2.id则可能会出现这个问题,但是我们使用e1.getId() == e2.getId()就不会出现这个问题。
文章引用:https://www.oschina.net/quest...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/71688.html
摘要:它也是用来判断两个对象是否相等,所以也得分不同的情况来说明。什么是的作用是获取哈希码,也称为散列码它返回的一个整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。它定义在的中,这就意味着中的任何类都包含有函数。 前言 万丈高楼平地起,今天的聊点基础而又经常让人忽视的话题,比如==与equals()区别?为何当我们重写完equals()后也要有必要去重写hashcode()呢? .....
摘要:方法提供了对象的值,是一个方法,返回的默认值与一致。通常这个值是对象头部的一部分二进制位组成的数字,具有一定的标识对象的意义存在,但绝不定于地址。与的关系相等两个对象,则一定要相等。 Java基础系列 Java的hashcode与equals方法 Java类初始化顺序 ThreadPoolExecutor线程池如何弹性伸缩 HashMap的几个要点 Integer的缓存 什么场景下使...
摘要:在中对象是一切对象都会自动继承的一个类,在这个类中定义的属性和方法可以说是每个类都必须的。这里有必要说说这里对象里面的几个方法返回该对象的哈希码值。这些基于表的集合,只能要求被存放的对象实现自己的方法,保证的均匀性。 Object 在Java中Object对象是一切对象都会自动继承的一个类,在这个类中定义的属性和方法可以说是每个类都必须的。 这里有必要说说这里对象里面的几个方法 has...
摘要:地址面试必备最最最常见的面试题总结第一周一中的值传递和引用传递非常重要首先要明确的是对象传递数组类接口是引用传递,原始类型数据整型浮点型字符型布尔型传递是值传递。这个哈希码的作用是确定该对象在哈希表中的索引位置。 showImg(https://segmentfault.com/img/remote/1460000015923339?w=922&h=519); 这里会分享一些出现频率极...
摘要:不同的对象,建议有不同的。所以最好是让均匀的落在不同的。正确写法如下要对两个字段做联合去重时皮一下做,做,放入结果可能为这种情况就是违反了第条,放入了不同的。 我的第一篇文章 以前都在公司的文档里写,后来想想,还是自己找个地方记录下来吧。今天有个朋友问我hashcode的问题,记录下来,并稍微读下书寻求一点理论知识。问题如下有一个属性都是字符串的对象,想放入hashset中,要求,对某...
阅读 3156·2021-11-22 09:34
阅读 2795·2021-09-22 15:28
阅读 816·2021-09-10 10:51
阅读 1852·2019-08-30 14:22
阅读 2272·2019-08-30 14:17
阅读 2733·2019-08-30 11:01
阅读 2295·2019-08-29 17:19
阅读 3653·2019-08-29 13:17