热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

关于Equal和HashCode的实现

重点提示:Equals示例:PublicOverridesFunctionEquals(ByValobjAsObject

 

重点提示:

Equals示例:

Public Overrides Function Equals(ByVal obj As Object) As Boolean

'Check for null and compare run-time types.

If obj Is Nothing OrElse Not [GetType]().Equals(obj.GetType()) Then

Return False

End If

Dim p As Point = CType(obj, Point)

Return x = p.x AndAlso y = p.y

End Function 'Equals


public override bool Equals(Object obj) {

//Check for null and compare run-time types.

if (obj == null || GetType() != obj.GetType()) return false;

Point p = (Point)obj;

return (x == p.x) && (y == p.y);

}

GetHashCode示例:

Public Overrides Function GetHashCode() As Integer

Return a.GetHashCode() Xor b.GetHashCode() Xor c.GetHashCode()

End Function


public override int GetHashCode () {

return a.GetHashCode() ^ b.GetHashCode() ^ c.GetHashCode();

}



首先是几篇比较有意义的内容:


equals()反映的是对象或变量具体的值。

hashCode()是对象或变量通过哈希算法计算出的哈希值。

之所以有hashCode方法,是因为在批量的对象比较中,hashCode要比equals来得快,很多集合都用到了hashCode,比如HashTable


两个obj,如果equals()相等,hashCode()一定相等。

两个obj,如果hashCode()相等,equals()不一定相等(Hash散列值有冲突的情况,虽然概率很低)。

所以:

可以考虑在集合中,判断两个对象是否相等的规则是:

第一步,如果hashCode()相等,则查看第二步,否则不相等;

第二步,查看equals()是否相等,如果相等,则两obj相等,否则还是不相等。



1、首先equals()hashcode()这两个方法都是从object类中继承过来的。

equals()是对两个对象的地址值进行的比较(即比较引用是否相同)。

hashCode()是一个本地方法,它的实现是根据本地机器相关的。


2Java语言对equals()的要求如下,这些要求是必须遵循的:

? 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”

? 反射性:x.equals(x)必须返回是“true”

? 类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”

? 一致性:如果x.equals(y)返回是“true”,只要xy内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”

? 任何情况下,x.equals(null),永远返回是“false”x.equals(x不同类型的对象)永远返回是“false”


3equals()相等的两个对象,hashcode()一定相等;

反过来:hashcode()不等,一定能推出equals()也不等;

hashcode()相等,equals()可能相等,也可能不等。

引用:http://honda418.javaeye.com/blog/342731


Effective Java

讲得比较详细

equals()方法

1. 自反

2. 对称

3. 传递

4. 一致

5X非空,x.equals(null)返回false


为了实现高质量的equals()改写,effective java提醒我们要注意一下几点:

1. 使用==操作符检查是否指向同一个对象,这是一个性能优化的手段。

2. 使用instanceof来检查是否为某个类,同样也是性能优化的手段。

3. 把实参转换到正确的类型,上面一步保证了这一步不会有错误。

4. 检查类里的每一个关键域是否都相等。


hashCode()则是一种计算 对象的散列值



任何 classes 如果复写了 equals(), 便应该同时也复写 hashCode()


我的理解:

两个函数都是用来比较两个对象是否相等的。默认情况下,这两个函数通过比较两个对象的地址是否一致来判断两个对象是否相等。也就是说,两个对象只有拥有相同的引用,才可能保证equalhashcode的相同。

如果我们仅仅需要比较地址,则没必要重写这两个函数。但是现实情况是,我们有时候需要通过比较对象的值来判定两个对象是否相等。比如下面这个类:

Public Class Point

Public x as Integer

Public y as Integer

End Class

我们定义两个对象:Point1Point2对象:

Dim Point1 as Point=New Point()

Dim Point2 as Point=New Point()

Point1.x=1

Point1.y=1

Point2.x=1

Point2.y=1

很明显,Point1Point2对应相同的点(1,1),他们的值是相同的,但是如果使用equalhashcode来比较两个对象,他们却是不同的,因为他们在内存中是两个独立的对象,地址不一样。

我们需要的功能是比较值而不是地址,这时我们就需要重写Equal函数和GetHashCode函数,让他们来比较值相等。下面就是示例代码:

Equals() :

http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx

Visual Basic :

Imports System


Class Point

Inherits Object

Protected x, y As Integer


Public Sub New()

Me.x = 0

Me.y = 0

End Sub 'New


Public Sub New(ByVal X As Integer, ByVal Y As Integer)

Me.x = X

Me.y = Y

End Sub 'New


Public Overrides Function Equals(ByVal obj As Object) As Boolean

'Check for null and compare run-time types.

If obj Is Nothing OrElse Not [GetType]().Equals(obj.GetType()) Then

Return False

End If

Dim p As Point = CType(obj, Point)

Return x = p.x AndAlso y = p.y

End Function 'Equals


Public Overrides Function GetHashCode() As Integer

Return x ^ y

End Function 'GetHashCode

End Class 'Point


Class Point3D

Inherits Point

Private z As Integer


Public Sub New(ByVal X As Integer, ByVal Y As Integer, ByVal Z As Integer)

Me.x = X

Me.y = Y

Me.z = Z

End Sub 'New


Public Overrides Function Equals(ByVal obj As Object) As Boolean

Return MyBase.Equals(obj) AndAlso z = CType(obj, Point3D).z

End Function 'Equals


Public Overrides Function GetHashCode() As Integer

Return MyBase.GetHashCode() ^ z

End Function 'GetHashCode

End Class 'Point3D


Class [MyClass]

Public Shared Sub Main()

Dim point2D As New Point(5, 5)

Dim point3Da As New Point3D(5, 5, 2)

Dim point3Db As New Point3D(5, 5, 2)


If Not point2D.Equals(point3Da) Then

Console.WriteLine("point2D does not equal point3Da.")

End If

If Not point3Db.Equals(point2D) Then

Console.WriteLine("Likewise, point3Db does not equal point2D.")

End If

If point3Da.Equals(point3Db) Then

Console.WriteLine("However, point3Da equals point3Db.")

End If


End Sub 'Main

End Class '[MyClass]

' ----------------------------------

' Output should be:

'

' point2D does not equal point3Da.

' Likewise, point3Db does not equal point2D.

' However, point3Da equals point3Db.



C# :

using System;


class Point: Object {

protected int x, y;


public Point() {

this.x = 0;

this.y = 0;

}


public Point(int X, int Y) {

this.x = X;

this.y = Y;

}


public override bool Equals(Object obj) {

//Check for null and compare run-time types.

if (obj == null || GetType() != obj.GetType()) return false;

Point p = (Point)obj;

return (x == p.x) && (y == p.y);

}


public override int GetHashCode() {

return x ^ y;

}

}



class Point3D: Point {

int z;


public Point3D(int X, int Y, int Z) {

this.x = X;

this.y = Y;

this.z = Z;

}


public override bool Equals(Object obj) {

return base.Equals(obj) && z == ((Point3D)obj).z;

}


public override int GetHashCode() {

return base.GetHashCode() ^ z;

}

}


class MyClass {


public static void Main() {

Point point2D = new Point(5, 5);

Point3D point3Da = new Point3D(5, 5, 2);

Point3D point3Db = new Point3D(5, 5, 2);


if (!point2D.Equals(point3Da)) {

Console.WriteLine("point2D does not equal point3Da.");

}

if (!point3Db.Equals(point2D)) {

Console.WriteLine("Likewise, point3Db does not equal point2D.");

}

if (point3Da.Equals(point3Db)) {

Console.WriteLine("However, point3Da equals point3Db.");

}


}

}

// ----------------------------------

// Output should be:

//

// point2D does not equal point3Da.

// Likewise, point3Db does not equal point2D.

// However, point3Da equals point3Db.


GetHashCode() :

http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

Visual Basic :

Imports System


Public Class SomeType

Public Overrides Function GetHashCode() As Integer

Return 0

End Function

End Class



Public Class AnotherType

Public Overrides Function GetHashCode() As Integer

Return 1

End Function

End Class


Public Class LastType

Public Overrides Function GetHashCode() As Integer

Return 2

End Function

End Class


Public Class Demo

Private a As New SomeType()

Private b As New AnotherType()

Private c As New LastType()


Public Overrides Function GetHashCode() As Integer

Return a.GetHashCode() Xor b.GetHashCode() Xor c.GetHashCode()

End Function

End Class



C# :

using System;


public class SomeType {

public override int GetHashCode() {

return 0;

}

}


public class AnotherType {

public override int GetHashCode() {

return 1;

}

}


public class LastType {

public override int GetHashCode() {

return 2;

}

}


public class MyClass {

SomeType a = new SomeType();

AnotherType b = new AnotherType();

LastType c = new LastType();


public override int GetHashCode () {

return a.GetHashCode() ^ b.GetHashCode() ^ c.GetHashCode();

}

}


几种常见的HashCode计算方法:

http://www.javaeye.com/topic/170219

1、 把某个非零常数值,比如17,保存在一个叫result的int类型的变量中。

2、 对于对象中的关键域f(指equals方法中考虑的每一个域),完成以下步骤:

A、为该域计算int类型的散列码c:

I、如果该域是boolean类型,则计算(f ? 0 : 1)。

II、如果该域是byte、char、short或者int类型,则计算(int)f。

III、如果该域是long类型,则计算(int)(f ^ f ( f >> 32 ) )。

IV、如果该域是float类型,则计算Float.floatToInitBits( f )。

V、如果该域是double类型,则计算Double.doubleToLongBits( f )得到一个long类型的值,再执行步骤III。

VI、如果该域是一个对象引用,并且该类的equals方法通过递归调用equals的方式来比较这个域,则同样对这个递归调用hashCode。如果要求一个更为复杂的比较,则为这个域计算一个规范表示,然后针对这个范式表示调用hashCode。如果这个域为NULL,则返回0或者其他常数。

VII、如果该域是一个数组,则把每个元素当作单独的域来处理。也就是说,递归地应用上述规则,对每个重要的元素计算一个散列码,然后根据步骤B中的做法把这些散列码组合起来。

B、按照下面的公式,把上面步骤的C组合到result中:

result = 17 * result + c;

3、 返回result。

4、 写完后测试是否相等的实例具有相同的散列码。


推荐阅读
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 本文介绍了在wepy中运用小顺序页面受权的计划,包含了用户点击作废后的从新受权计划。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • MPLS VP恩 后门链路shamlink实验及配置步骤
    本文介绍了MPLS VP恩 后门链路shamlink的实验步骤及配置过程,包括拓扑、CE1、PE1、P1、P2、PE2和CE2的配置。详细讲解了shamlink实验的目的和操作步骤,帮助读者理解和实践该技术。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • 本文介绍了Java中Currency类的getInstance()方法,该方法用于检索给定货币代码的该货币的实例。文章详细解释了方法的语法、参数、返回值和异常,并提供了一个示例程序来说明该方法的工作原理。 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
author-avatar
mobiledu2502891563
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有