- 浏览: 425112 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
burningblood:
最近也遇到了这个细节问题。我用的是4,里面没有 get.rel ...
httpclient的并发连接问题 -
greatwqs:
使用HttpURLConnection注意设置超时 -
qinweilh:
...
tomcat报错:standardServer.await: create[8005]: -
jayyunfei:
还是不很明白
JPA entityManager的管理 -
a418040445:
...
Calendar
前言
在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,就要设计另外一个。在多数情况 下,这两个函数是不用考虑的,直接使用它们的默认设计就可以了。但是在一些情况下,这两个函数最好是自己设计,才能确保整个程序的正常运行。最常见的是当 一个对象被加入收集对象(collection object)时,这两个函数必须自己设计。更细化的定义是:如果你想将一个对象A放入另一个收集对象B里,或者使用这个对象A为查找一个元对象在收集对 象B里位置的钥匙,并支持是否容纳,删除收集对象B里的元对象这样的操作,那么,equals()和hashCode()函数必须开发者自己定义。其他情 况下,这两个函数是不需要定义的。
equals():
它是用于进行两个对象的比较的,是对象内容的比较,当然也能用于进行对象参阅值的比较。什么是对象参阅值的比较?就是两个参阅变量的值得比较,我们 都知道参阅变量的值其实就是一个数字,这个数字可以看成是鉴别不同对象的代号。两个对象参阅值的比较,就是两个数字的比较,两个代号的比较。这种比较是默 认的对象比较方式,在Object这个对象中,这种方式就已经设计好了。所以你也不用自己来重写,浪费不必要的时间。
对象内容的比较才是设计equals()的真正目的,Java语言对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”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
- 任何情况下,x.equals(null),永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”。
hashCode():
这
个函数返回的就是一个用来进行赫希操作的整型代号,请不要把这个代号和前面所说的参阅变量所代表的代号弄混了。后者不仅仅是个代号还具有在内存中才查找对
象的位置的功能。hashCode()所返回的值是用来分类对象在一些特定的收集对象中的位置。这些对象是HashMap, Hashtable,
HashSet,等等。这个函数和上面的equals()函数必须自己设计,用来协助HashMap, Hashtable,
HashSet,等等对自己所收集的大量对象进行搜寻和定位。
这些收集对象究竟如何工作的,想象每个元对象hashCode是一个箱子的
编码,按照编码,每个元对象就是根据hashCode()提供的代号归入相应的箱子里。所有的箱子加起来就是一个HashSet,HashMap,或
Hashtable对象,我们需要寻找一个元对象时,先看它的代码,就是hashCode()返回的整型值,这样我们找到它所在的箱子,然后在箱子里,每
个元对象都拿出来一个个和我们要找的对象进行对比,如果两个对象的内容相等,我们的搜寻也就结束。这种操作需要两个重要的信息,一是对象的
hashCode(),还有一个是对象内容对比的结果。
hashCode()的返回值和equals()的关系如下:
- 如果x.equals(y)返回“true”,那么x和y的hashCode()必须相等。
- 如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。
为什么这两个规则是这样的,原因其实很简单,拿HashSet来说吧,HashSet可以拥有一个或更多的箱子,在同一个箱子中可以有一个
或更多的独特元对象(HashSet所容纳的必须是独特的元对象)。这个例子说明一个元对象可以和其他不同的元对象拥有相同的hashCode。但是一个
元对象只能和拥有同样内容的元对象相等。所以这两个规则必须成立。
设计这两个函数所要注意到的:
如果你设计的对象类型并不使用于收集性对象,那么没有必要自己再设计这两个函数的处理方式。这是正确的面向对象设计方法,任何用户一时用不到的功能,就先不要设计,以免给日后功能扩展带来麻烦。
如果你在设计时想别出心裁,不遵守以上的两套规则,那么劝你还是不要做这样想入非非的事。我还没有遇到过哪一个开发者和我说设计这两个函数要违背前面说的两个规则,我碰到这些违反规则的情况时,都是作为设计错误处理。
当一个对象类型作为收集型对象的元对象时,这个对象应该拥有自己处理equals(),和/或处理hashCode()的设计,而且要遵守前面所说 的两种原则。equals()先要查null和是否是同一类型。查同一类型是为了避免出现ClassCastException这样的异常给丢出来。查 null是为了避免出现NullPointerException这样的异常给丢出来。
如果你的对象里面容纳的数据过多,那么这两个函数 equals()和hashCode()将会变得效率低。如果对象中拥有无法serialized的数据,equals()有可能在操作中出现错误。想象 一个对象x,它的一个整型数据是transient型(不能被serialize成二进制数据流)。然而equals()和hashCode()都有依靠 这个整型数据,那么,这个对象在serialization之前和之后,是否一样?答案是不一样。因为serialization之前的整型数据是有效的 数据,在serialization之后,这个整型数据的值并没有存储下来,再重新由二进制数据流转换成对象后,两者(对象在serialization 之前和之后)的状态已经不同了。这也是要注意的。
知道以上这些能够帮助你:
1. 进行更好的设计和开发。
2. 进行更好的测试案例开发。
3. 在面试过程中让面试者对你的学识渊博感到满意。
hashCode的作用
总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是 Set。你知道它们的区别吗?前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。那么这里就有一个比较严重的问题了:要想保证元素 不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后 添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次 equals方法。这显然会大大降低效率。 于是,Java采用了哈希表的原理。哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。哈希算法也称为散列算法,是 将数据依特定算法直接指定到一个地址上。如果详细讲解哈希算法,那需要更多的文章篇幅,我在这里就不介绍了。初学者可以这样理解,hashCode方法实 际上返回的就是对象存储的物理地址(实际可能并不是)。 这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以 直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散 列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。 所以,Java对于eqauls方法和hashCode方法是这样规定的:1、如果两个对象相同,那么它们的hashCode值一定要相同;2、如果两个 对象的hashCode相同,它们并不一定相同 上面说的对象相同指的是用eqauls方法比较。 你当然可以不按要求去做了,但你会发现,相同的对象可以出现在Set集合中。同时,增加新元素的效率会大大下降。
我们知道,equals()函数是用来做比较的。java中的比较有两种:一种是内存地址的比较,一种是内容的比较。而比较个体也有两种:一种是简单类型(这类简单说来无所谓内存地址的比较或者内容比较的区别);还有一种是对象的比较,本文中说的主要是后者
在java中,(对象)内存地址的比较,是通过==完成的。比如
这样的语句中,我们认为,如果obj1和obj2的内存地址相同,则返回true
而equals()通常是比较内容的。这里说“通常” ,是因为在最根本的Object类中,equal()函数做的是地址的比较。而在其他几乎所有的类中,equals()都经过重载,进行内容的比较。
而在说equals()的时候我们还涉及hashCode()是因为在有些应用中(比如,HashMap的key是对象),必须在重载equals()的同时重载hashCode()。因为java中默认(Object)的hashCode是根据对象的地址计算得到的。
我们通常不会注意到这个问题,因为我们通常所使用的key都是简单类型,或者是String, Long等一些特殊的对象(其特殊性请参看笔者在写java 浅拷贝和深拷贝时的讨论),这时候,这个问题被我们无意间绕过了
有人已经概括了这种我们忽略了的情况:“如果你想将一个对象A放入另一个收集(集合)对象B里,或者使用这个对象A为查找一个元对象在收集对 象B里位置的钥匙(key),并支持是否容纳(isContains()),删除收集对象B里的元对象(remove()?)这样的操作,那 么,equals()和hashCode()函数必须开发者自己定义。” (括号为笔者添加)
发表评论
-
糟糕透顶的axis2
2015-02-06 15:27 856我记得很早以前在网上看过文章,大致讲axis2的质量如何 ... -
使用java连接https的问题
2012-03-19 15:41 845在使用hudson的过程中,我们需要发送邮件的功能。但是公司的 ... -
SSL exception: "No subject alternative names matching IP address ..." & "No name
2012-02-08 09:35 10683When you want to establish an S ... -
ResourceBundle加载文件的顺序
2011-12-24 15:01 1363If a ResourceBundle class for ... -
异常处理框架
2011-09-07 14:57 818The Nature of Exceptions Bro ... -
httpclient的并发连接问题
2011-05-24 16:14 6683昨天的搜索系统又出状况了,几个库同时重建索引变得死慢。经 ... -
java connect https
2011-05-04 15:37 988When I use java to connect HTTP ... -
jvm的高性能
2011-04-25 13:48 806jdk将源代码编译成字节码之后,由JVM在运行期对其进行解释执 ... -
java annotation
2011-03-10 14:58 898JDK内置的annotaion 1. @Target ... -
java字节码的操纵
2011-03-09 16:35 1528http://www.infoq.com/cn/article ... -
java 范型
2011-03-09 15:15 752Java泛型(generics)是JDK 5中引入的一个新特性 ... -
正确使用 Volatile 变量
2011-03-04 09:34 787Java 语言中的 volatile 变 ... -
java中Thread与Runnable的区别
2011-02-25 20:42 1742在java中可有两种方式实现多线程,一种是继承Thread类, ... -
copy-on-write
2010-12-08 10:29 927Copy-on-write (sometimes refe ... -
synchronized原理
2010-11-29 14:40 1855每个JAVA对象都有一把锁, 当有多个线程同时访问共享资源的时 ... -
Map 四种同步方式的性能比较
2010-11-25 11:50 969如果需要使 Map 线程安全,大致有这么四种方法: 1、 ... -
Java中HashMap,LinkedHashMap,TreeMap的区别
2010-11-25 11:49 1744java为数据结构中的映射 ... -
java的内存泄漏
2010-11-25 10:52 10451 引言 Java的一个重要优点就是通过垃圾收集器 ... -
java map
2010-11-25 10:40 11341. Map key: 同一个key必须hashcode相同。 ... -
Calendar
2010-09-17 15:44 1454对于时间的运算,应当使用Calendar: Calendar ...
相关推荐
"Java重写equals及hashcode方法流程解析" Java中的equals和hashCode方法是两个非常重要的方法,它们都是Object类中的方法。在实际开发中,正确地重写这两个方法对于确保程序的正确性和性能至关重要。下面,我们将...
总的来说,理解并正确使用`equals()`和`hashCode()`方法对于编写高质量的Java代码至关重要,尤其是在处理集合框架中的对象时。这两个方法的合理实现能确保对象比较的正确性和哈希表操作的效率。希望这个深入解析能...
### hashCode和equals方法详解 ...通过以上分析,我们可以看到`hashCode`和`equals`方法在Java中扮演着非常重要的角色,尤其是在集合框架中。正确地实现这两个方法可以大大提高程序的性能和可维护性。
在Java编程语言中,`hashCode()`和`equals()`方法是非常重要的概念,它们主要用于处理对象的唯一标识和对象之间的相等性判断。正确地实现这两个方法对于确保程序的高效运行至关重要。 #### `hashCode()`方法解析 `...
`equals()` 方法用于判断两个对象是否相等,而 `hashCode()` 方法则与对象的哈希值有关,这对于理解和使用Java中的集合框架至关重要。 `equals()` 方法是Object类的一个成员方法,它的默认行为是基于引用比较,即...
每个Table对应一个Java类,Column则作为类的成员变量,主键和外键可以转化为getter和setter方法,以及可能的构造函数和equals、hashCode方法。这样,开发人员就可以直接使用这些Java Bean进行业务开发,无需手动编写...
此外,Objects类(在Java 7引入)提供了equals、hashCode和requireNonNull等方法,增强了对象比较和非空检查的功能。 数据处理工具类往往涉及集合操作。Java的util包包含了多种集合框架类,如List、Set、Map等。...
例如,通过重写`equals()`和`hashCode()`方法来检查对象的唯一性,或者创建独立的验证方法来处理复杂的业务逻辑。 在工具方面,有一些IDE插件,如IntelliJ IDEA的Inspections,可以在编码时提供实时的校验提示,...
3. **兼容数据结构**:许多Java集合框架中的数据结构(如HashSet、HashMap)依赖于对象的`equals`和`hashCode`方法来判断元素的唯一性。如果未正确重写`equals`方法,这些数据结构可能会出现异常行为。 #### 三、...
### hashCode的作用 在Java编程语言中,`hashCode`方法是一个重要的概念,主要用于对象的查找与存储,尤其是在集合框架中有着广泛...在实际开发中,应当注意对这两个方法的合理使用和重写,以满足具体应用场景的需求。
Object类提供了几个核心的方法,这些方法在处理对象时非常关键,包括equals()、hashCode()、toString()、clone()、finalize()等。 1. **equals() 方法**: - 默认情况下,equals() 方法比较的是对象的引用,即检查...
对于面试指南,了解String、StringBuilder和StringBuffer的差异,理解对象相等和引用相等的区别,以及equals和hashCode的关系至关重要。Java序列化中,可以通过transient关键字排除字段。 总之,Java高级资深核心...
### Java 最常见 200+ 面试题全解析:面试必备 #### Java 基础 1. **JDK 和 JRE 的区别** - **JDK**(Java Development Kit):Java 开发工具包,包含了 Java 的运行环境(JRE)以及 Java 编译器和其他开发工具...
4. 可能还包括构造函数、toString()、equals()和hashCode()等常用方法。 生成DAO类的过程中,会包含以下内容: 1. 定义接口,接口中的方法对应于基本的CRUD(Create、Read、Update、Delete)操作,如insert()、...
`Object`类提供了许多方法,其中包括`toString()`、`equals()`和`hashCode()`,这些都是用于对象的基本操作。对于`String`对象,它们在Java中的处理和比较有一些特殊的规则。 1. **对象的相等性比较**: - 原生...