java中为什么重写equals时必须重写hashCode方法

小编给大家分享一下java中为什么重写equals时必须重写hashCode方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

创新互联公司一直在为企业提供服务,多年的磨炼,使我们在创意设计,成都营销网站建设到技术研发拥有了开发经验。我们擅长倾听企业需求,挖掘用户对产品需求服务价值,为企业制作有用的创意设计体验。核心团队拥有超过十年以上行业经验,涵盖创意,策化,开发等专业领域,公司涉及领域有基础互联网服务达州托管服务器app软件开发公司、手机移动建站、网页设计、网络整合营销。

 先让我们来看看Object类源码

/**
 * Returns a hash code value for the object. This method is
 * supported for the benefit of hash tables such as those provided by
 * {@link java.util.HashMap}.
 * 

 * The general contract of {@code hashCode} is:  * 

     * 
  • Whenever it is invoked on the same object more than once during  * an execution of a Java application, the {@code hashCode} method  * must consistently return the same integer, provided no information  * used in {@code equals} comparisons on the object is modified.  * This integer need not remain consistent from one execution of an  * application to another execution of the same application.  * 
  • If two objects are equal according to the {@code equals(Object)}  * method, then calling the {@code hashCode} method on each of  * the two objects must produce the same integer result.  * 
  • It is not required that if two objects are unequal  * according to the {@link java.lang.Object#equals(java.lang.Object)}  * method, then calling the {@code hashCode} method on each of the  * two objects must produce distinct integer results. However, the  * programmer should be aware that producing distinct integer results  * for unequal objects may improve the performance of hash tables.  * 
 * 

 * As much as is reasonably practical, the hashCode method defined by  * class {@code Object} does return distinct integers for distinct  * objects. (This is typically implemented by converting the internal  * address of the object into an integer, but this implementation  * technique is not required by the  * Java™ programming language.)  *  * @return a hash code value for this object.  * @see java.lang.Object#equals(java.lang.Object)  * @see java.lang.System#identityHashCode  */  public native int hashCode();

/**
 * Indicates whether some other object is "equal to" this one.
 * 

 * The {@code equals} method implements an equivalence relation  * on non-null object references:  * 

     * 
  • It is reflexive: for any non-null reference value  * {@code x}, {@code x.equals(x)} should return  * {@code true}.  * 
  • It is symmetric: for any non-null reference values  * {@code x} and {@code y}, {@code x.equals(y)}  * should return {@code true} if and only if  * {@code y.equals(x)} returns {@code true}.  * 
  • It is transitive: for any non-null reference values  * {@code x}, {@code y}, and {@code z}, if  * {@code x.equals(y)} returns {@code true} and  * {@code y.equals(z)} returns {@code true}, then  * {@code x.equals(z)} should return {@code true}.  * 
  • It is consistent: for any non-null reference values  * {@code x} and {@code y}, multiple invocations of  * {@code x.equals(y)} consistently return {@code true}  * or consistently return {@code false}, provided no  * information used in {@code equals} comparisons on the  * objects is modified.  * 
  • For any non-null reference value {@code x},  * {@code x.equals(null)} should return {@code false}.  * 
 * 

 * The {@code equals} method for class {@code Object} implements  * the most discriminating possible equivalence relation on objects;  * that is, for any non-null reference values {@code x} and  * {@code y}, this method returns {@code true} if and only  * if {@code x} and {@code y} refer to the same object  * ({@code x == y} has the value {@code true}).  * 

 * Note that it is generally necessary to override the {@code hashCode}  * method whenever this method is overridden, so as to maintain the  * general contract for the {@code hashCode} method, which states  * that equal objects must have equal hash codes.  *  * @param obj the reference object with which to compare.  * @return {@code true} if this object is the same as the obj  *  argument; {@code false} otherwise.  * @see #hashCode()  * @see java.util.HashMap  */  public boolean equals(Object obj) {  return (this == obj);  }

hashCode:是一个native方法,返回的是对象的内存地址,

equals:对于基本数据类型,==比较的是两个变量的值。对于引用对象,==比较的是两个对象的地址。

接下来我们看下hashCode的注释

1.在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。
从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
2.如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
3.如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么两个对象不一定必须产生不同的整数结果。
但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。

从hashCode的注释中我们看到,hashCode方法在定义时做出了一些常规协定,即

1,当obj1.equals(obj2) 为 true 时,obj1.hashCode() == obj2.hashCode()

2,当obj1.equals(obj2) 为 false 时,obj1.hashCode() != obj2.hashCode()

hashcode是用于散列数据的快速存取,如利用HashSet/HashMap/Hashtable类来存储数据时,都是根据存储对象的hashcode值来进行判断是否相同的。如果我们将对象的equals方法重写而不重写hashcode,当我们再次new一个新的对象的时候,equals方法返回的是true,但是hashCode方法返回的就不一样了,如果需要将这些对象存储到结合中(比如:Set,Map ...)的时候就违背了原有集合的原则,下面让我们通过一段代码看下。

/**
 * @see Person
 * @param args
 */
 public static void main(String[] args)
 {
 HashMap map = new HashMap();

 Person p = new Person("jack",22,"男");
 Person p1 = new Person("jack",22,"男");

 System.out.println("p的hashCode:"+p.hashCode());
 System.out.println("p1的hashCode:"+p1.hashCode());
 System.out.println(p.equals(p1));
 System.out.println(p == p1);

 map.put(p,888);
 map.put(p1,888);
 map.forEach((key,val)->{
  System.out.println(key);
  System.out.println(val);
 });
 }

equals和hashCode方法的都不重写

public class Person
{
 private String name;

 private int age;

 private String sex;

 Person(String name,int age,String sex){
 this.name = name;
 this.age = age;
 this.sex = sex;
 }
}
p的hashCode:356573597
p1的hashCode:1735600054
false
false
com.blueskyli.练习.Person@677327b6
com.blueskyli.练习.Person@1540e19d

只重写equals方法

public class Person
{
 private String name;

 private int age;

 private String sex;

 Person(String name,int age,String sex){
 this.name = name;
 this.age = age;
 this.sex = sex;
 }

 @Override public boolean equals(Object obj)
 {
 if(obj instanceof Person){
  Person person = (Person)obj;
  return name.equals(person.name);
 }
 return super.equals(obj);
 }
}
p的hashCode:356573597
p1的hashCode:1735600054
true
false
com.blueskyli.练习.Person@677327b6
com.blueskyli.练习.Person@1540e19d

equals和hashCode方法都重写

public class Person
{
 private String name;

 private int age;

 private String sex;

 Person(String name,int age,String sex){
 this.name = name;
 this.age = age;
 this.sex = sex;
 }

 @Override public boolean equals(Object obj)
 {
 if(obj instanceof Person){
  Person person = (Person)obj;
  return name.equals(person.name);
 }
 return super.equals(obj);
 }

 @Override public int hashCode()
 {
 return name.hashCode();
 }
}
p的hashCode:3254239
p1的hashCode:3254239
true
false
com.blueskyli.练习.Person@31a7df

我们知道map是不允许存在相同的key的,由上面的代码可以知道,如果不重写equals和hashCode方法的话会使得你在使用map的时候出现与预期不一样的结果,具体equals和hashCode如何重写,里面的逻辑如何实现需要根据现实当中的业务来规定。

总结:

1,两个对象,用==比较比较的是地址,需采用equals方法(可根据需求重写)比较。

2,重写equals()方法就重写hashCode()方法。

3,一般相等的对象都规定有相同的hashCode。

4,String类重写了equals和hashCode方法,比较的是值。

5,重写hashcode方法为了将数据存入HashSet/HashMap/Hashtable(可以参考源码有助于理解)类时进行比较

以上是“java中为什么重写equals时必须重写hashCode方法”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注创新互联行业资讯频道!


标题名称:java中为什么重写equals时必须重写hashCode方法
本文来源:http://scyanting.com/article/ispocs.html