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

在上一篇博文

先让我们来看看Object类源码

/*** Returns a hash code value for the object. This method is

* supported for the benefit of hash tables such as those provided by

* {@linkjava.util.HashMap}.

*

* The general contract of {@codehashCode} is:

*

*

Whenever it is invoked on the same object more than once during

* an execution of a Java application, the {@codehashCode} method

* must consistently return the same integer, provided no information

* used in {@codeequals} 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 {@codeequals(Object)}

* method, then calling the {@codehashCode} 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 {@linkjava.lang.Object#equals(java.lang.Object)}

* method, then calling the {@codehashCode} 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 {@codeObject} 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.)

*

*@returna hash code value for this object.

*@seejava.lang.Object#equals(java.lang.Object)

*@seejava.lang.System#identityHashCode*/

public native int hashCode();

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

*

* The {@codeequals} method implements an equivalence relation

* on non-null object references:

*

*

It is reflexive: for any non-null reference value

* {@codex}, {@codex.equals(x)} should return

* {@codetrue}.

*

It is symmetric: for any non-null reference values

* {@codex} and {@codey}, {@codex.equals(y)}

* should return {@codetrue} if and only if

* {@codey.equals(x)} returns {@codetrue}.

*

It is transitive: for any non-null reference values

* {@codex}, {@codey}, and {@codez}, if

* {@codex.equals(y)} returns {@codetrue} and

* {@codey.equals(z)} returns {@codetrue}, then

* {@codex.equals(z)} should return {@codetrue}.

*

It is consistent: for any non-null reference values

* {@codex} and {@codey}, multiple invocations of

* {@codex.equals(y)} consistently return {@codetrue}

* or consistently return {@codefalse}, provided no

* information used in {@codeequals} comparisons on the

* objects is modified.

*

For any non-null reference value {@codex},

* {@codex.equals(null)} should return {@codefalse}.

*

*

* The {@codeequals} method for class {@codeObject} implements

* the most discriminating possible equivalence relation on objects;

* that is, for any non-null reference values {@codex} and

* {@codey}, this method returns {@codetrue} if and only

* if {@codex} and {@codey} refer to the same object

* ({@codex == y} has the value {@codetrue}).

*

* Note that it is generally necessary to override the {@codehashCode}

* method whenever this method is overridden, so as to maintain the

* general contract for the {@codehashCode} method, which states

* that equal objects must have equal hash codes.

*

*@paramobj the reference object with which to compare.

*@return{@codetrue} if this object is the same as the obj

* argument; {@codefalse} otherwise.

*@see#hashCode()

*@seejava.util.HashMap*/

public booleanequals(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 ...)的时候就违背了原有集合的原则,下面让我们通过一段代码看下。

/***@seePerson

*@paramargs*/

public static voidmain(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 classPerson

{privateString name;private intage;privateString sex;

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

}

}

p的hashCode:356573597p1的hashCode:1735600054

false

falsecom.blueskyli.练习.Person@677327b6888com.blueskyli.练习.Person@1540e19d

888

只重写equals方法

public classPerson

{privateString name;private intage;privateString sex;

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

}

@Overridepublic booleanequals(Object obj)

{if(obj instanceofPerson){

Person person=(Person)obj;returnname.equals(person.name);

}return super.equals(obj);

}

}

p的hashCode:356573597p1的hashCode:1735600054

true

falsecom.blueskyli.练习.Person@677327b6888com.blueskyli.练习.Person@1540e19d

888

equals和hashCode方法都重写

public classPerson

{privateString name;private intage;privateString sex;

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

}

@Overridepublic booleanequals(Object obj)

{if(obj instanceofPerson){

Person person=(Person)obj;returnname.equals(person.name);

}return super.equals(obj);

}

@Overridepublic inthashCode()

{returnname.hashCode();

}

}

p的hashCode:3254239p1的hashCode:3254239

true

falsecom.blueskyli.练习.Person@31a7df888

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

总结:

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

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

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值