- 浏览: 648596 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (142)
- Android (38)
- hibernate (12)
- java基础 (18)
- spring (5)
- struts1.x (8)
- struts2.x (7)
- web开发 (11)
- tomact (1)
- jbpm3.2 (2)
- jpa (2)
- strutstest (1)
- js (3)
- WebWork (2)
- 数据库 (5)
- mysql (6)
- myeclipse和eclipse (8)
- java与办公 (2)
- linux (10)
- 性能调优 (2)
- 搜索引擎 (1)
- urlrewritefilter (1)
- Git (3)
- Dos (1)
- Chrome (1)
- PLMN (1)
最新评论
-
3xxx:
你这个靠谱。谢谢。
git push用法和常见问题分析 -
lord_is_layuping:
mark
git push用法和常见问题分析 -
calatustela:
@Resource是名字优先注入,可以用来注入Map之类的常量 ...
spring 注解@Resource 和 @Autowired -
Mr.Cheney:
repo sync 下载耗时太久了, 有没有国内的站可下编译环 ...
使用repo下载google 的android4.4 源码,和编译.运行 -
北极光之吻:
kslinabc 写道请问楼主,4.4下载下来有多大,为啥我这 ...
使用repo下载google 的android4.4 源码,和编译.运行
重写hashCode()时最重要的原因就是:无论何时,对同一个对象调用hashCode()都应该生成同样的值。如果在将一个对象用put()方法添加进HashMap时产生一个hashCode()值,而用get()取出时却产生了另外一个 hashCode()值,那么就无法重新取得该对象了。所以,如果你的hashCode()方法依赖于对象中易变的数据,那用户就要小心了,因为此数据发生变化时,hashCode()就会产生一个不同的hash码,相当于产生了一个不同的“键”。
总的来说,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集合中。同时,增加新元素的效率会大大下降。
hashcode这个方法是用来鉴定2个对象是否相等的。 那你会说,不是还有equals这个方法吗? 不错,这2个方法都是用来判断2个对象是否相等的。但是他们是有区别的。 一般来讲,equals这个方法是给用户调用的,如果你想判断2个对象是否相等,你可以重写equals方法,然后在代码中调用,就可以判断他们是否相等 了。简单来讲,equals方法主要是用来判断从表面上看或者从内容上看,2个对象是不是相等。举个例子,有个学生类,属性只有姓名和性别,那么我们可以 认为只要姓名和性别相等,那么就说这2个对象是相等的。 hashcode方法一般用户不会去调用,比如在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就判断了hashcode 这个方法,而且也用到了equals方法。这里不可以重复是说equals和hashcode只要有一个不等就可以了!所以简单来讲,hashcode相 当于是一个对象的编码,就好像文件中的md5,他和equals不同就在于他返回的是int型的,比较起来不直观。我们一般在覆盖equals的同时也要 覆盖hashcode,让他们的逻辑一致。举个例子,还是刚刚的例子,如果姓名和性别相等就算2个对象相等的话,那么hashcode的方法也要返回姓名 的hashcode值加上性别的hashcode值,这样从逻辑上,他们就一致了。 要从物理上判断2个对象是否相等,用==就可以了。
Object的hashCode()方法,返回的是当前对象的内存地址。下次如果我们需要取一个一样的“键”对应的键值对的时候,我们就无法得到一样的hashCode值了。因为我们后来创建的“键”对象已经不是存入HashMap中的那个内存地址的对象了。
我们看一个简单的例子,就能更加清楚的理解上面的意思。假定我们写了一个类:Person (人),我们判断一个对象“人”是否指向同一个人,只要知道这个人的身份证号一直就可以了。
先来个没有重写Code类的hashcode()的例子吧,看看是什么效果:
package com.fit;
import java.util.HashMap;
/**
* 身份证类
*
* @author ZYD
*
*/
public class Code {
/**
* 身份证号码,一旦确定就不能更改
*/
private final int id;
public int getId() {
return id;
}
/**
* 通过构造方法确定身份证号码
*
* @param id
*/
public Code(int id) {
this.id = id;
}
/**
* 重写equals()方法
*/
public boolean equals(Object o) {
// 如果地址一样,则两个对象相同
if (this == o) {
return true;
}
// 如果两个对象是同一类型,则比较其属性值是否都相同。如果都相同,则说明两个对象也相同;否则,说明这两个对象不相同。
if (o instanceof Code) {
Code co = (Code) o;
boolean b = (co.id == this.id);
return b;
}
return false;
}
/**
* 重写toString()方法
*/
public String toString() {
return "【身份证】:" + id;
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
HashMap<Code, Person> map = new HashMap<Code, Person>();
Person p1 = new Person(new Code(10001),"张三");
Person p2 = new Person(new Code(10002),"李四");
map.put(p1.getCode(), p1);
map.put(p2.getCode(), p2);
System.out.println("HashMap 中存放的人员信息:\n"+map);
//张三改名为张山,身份证号不变。
Person p3 = new Person(new Code(10001),"张山");
map.put(p3.getCode(), p3);
System.out.println("张三改名为张山后 HashMap 中存放的人员信息:\n"+map);
//查找身份证为10001 的人员信息
System.out.println("查找身份证为:10001 的人员信息:"+map.get(new Code(10001)));
}
}
/**
* 人类
* @author Administrator
*
*/
class Person {
/**
* 每一个成人都有一个身份证
*/
private Code code;
/**
* 姓名
*/
private String name;
public Code getCode() {
return code;
}
public void setCode(Code code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person() {
}
public Person(Code code, String name) {
this.code = code;
this.name = name;
}
/**
* 重写equals()方法 当两个人得身份证号相同以及姓名相同时,表示这两个人是同一个人。
*/
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof Person) {
Person p = (Person) o;
boolean b = this.code.equals(p.code) && this.name.equals(p.name);
return b;
}
return false;
}
/**
* 重写toString()方法
*/
public String toString() {
return "【姓名】:" + name + " ";
}
}
运行结果:
HashMap 中存放的人员信息:
{【身份证】:10002=【姓名】:李四 , 【身份证】:10001=【姓名】:张三 }
张三改名为张山后 HashMap 中存放的人员信息:
{【身份证】:10002=【姓名】:李四 , 【身份证】:10001=【姓名】:张三 , 【身份证】:10001=【姓名】:张山 }
查找身份证为:10001 的人员信息:null
从上面的结果可以看出:
我们所做的更新和查找操作都失败了。失败的原因就是我们的身份证类:Code 没有覆写hashCode()方法。这个时候,当查找一样的身份证号码的键值对的时候,使用的是默认的对象的内存地址来进行定位。这样,后面的所有的身份证号对象
new Code(10001)产生的hashCode()值都是不一样的,所以导致操作失败。
重写Code类的hashcode(),代码上:
package com.fit;
import java.util.HashMap;
/**
* 身份证类
*
* @author ZYD
*
*/
public class Code {
/**
* 身份证号码,一旦确定就不能更改
*/
private final int id;
public int getId() {
return id;
}
/**
* 通过构造方法确定身份证号码
*
* @param id
*/
public Code(int id) {
this.id = id;
}
/**
* 重写equals()方法
*/
public boolean equals(Object o) {
// 如果地址一样,则两个对象相同
if (this == o) {
return true;
}
// 如果两个对象是同一类型,则比较其属性值是否都相同。如果都相同,则说明两个对象也相同;否则,说明这两个对象不相同。
if (o instanceof Code) {
Code co = (Code) o;
boolean b = (co.id == this.id);
return b;
}
return false;
}
/**
* 重写hashcode()方法,以身份证号码作为hash码。
*
* @return
*/
public int hashCode() {
return id;
}
/**
* 重写toString()方法
*/
public String toString() {
return "【身份证】:" + id;
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
HashMap<Code, Person> map = new HashMap<Code, Person>();
Person p1 = new Person(new Code(10001),"张三");
Person p2 = new Person(new Code(10002),"李四");
map.put(p1.getCode(), p1);
map.put(p2.getCode(), p2);
System.out.println("HashMap 中存放的人员信息:\n"+map);
//张三改名为张山,身份证号不变。
Person p3 = new Person(new Code(10001),"张山");
map.put(p3.getCode(), p3);
System.out.println("张三改名为张山后 HashMap 中存放的人员信息:\n"+map);
//查找身份证为10001 的人员信息
System.out.println("查找身份证为:10001 的人员信息:"+map.get(new Code(10001)));
}
}
/**
* 人类
* @author Administrator
*
*/
class Person {
/**
* 每一个成人都有一个身份证
*/
private Code code;
/**
* 姓名
*/
private String name;
public Code getCode() {
return code;
}
public void setCode(Code code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person() {
}
public Person(Code code, String name) {
this.code = code;
this.name = name;
}
/**
* 重写equals()方法 当两个人得身份证号相同以及姓名相同时,表示这两个人是同一个人。
*/
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof Person) {
Person p = (Person) o;
boolean b = this.code.equals(p.code) && this.name.equals(p.name);
return b;
}
return false;
}
/**
* 重写toString()方法
*/
public String toString() {
return "【姓名】:" + name + " ";
}
}
运行效果:
HashMap 中存放的人员信息:
{【身份证】:10001=【姓名】:张三 , 【身份证】:10002=【姓名】:李四 }
张三改名为张山后 HashMap 中存放的人员信息:
{【身份证】:10001=【姓名】:张山 , 【身份证】:10002=【姓名】:李四 }
查找身份证为:10001 的人员信息:【姓名】:张山
发表评论
-
关于java List的remove方法导致的异常java.util.ConcurrentModificationException
2015-01-12 14:10 2747关于java List的remove方法导致的异常java. ... -
URI和URL的区别
2013-12-03 10:29 878URIs, URLs, and URNs 首先,URI, ... -
JSONObject与JSONArray的使用
2013-03-08 12:53 1161JSONObject与JSONArray的使用 一 ... -
比较常用的几个正则表达式(匹配数字)
2013-03-08 12:49 1325比较常用的几个正则表达式(匹配数字) 正则表达式用于字符串 ... -
java日期格式化、解析
2013-03-08 12:41 1554日期的格式化器普用的是SimpleDateFormat,它继 ... -
java.net.MalformedURLException: Protocol not found
2012-08-01 11:42 2282608-01 03:12:29.520: WARN/Syste ... -
Java各种数据库连接
2012-06-19 11:08 1049Java数据库连接接口(JDBC)是Java里定义的一套 ... -
在Eclipse中import sun.misc.BASE64Encoder,sun.misc.BASE64Decoder时出错
2012-06-22 00:05 2041今天在将输入的字符转换成base64编码后输出遇到一个问 ... -
getClass()
2012-06-23 15:47 1060Java反射学习 所谓反射,可以理解为在运行时期获取对象类型 ... -
Class.forName( )
2012-06-14 18:24 937在Java开发特别是数据库 ... -
深入研究java.lang.ThreadLocal类
2012-06-13 16:49 885http://lavasoft.blog.51cto.com/ ... -
Integer包装类的缓冲池
2012-06-21 20:28 1178public class AutoBox { ... -
如何得到各个字节码对应的实例对象( Class类型)
2012-06-18 21:51 1169类名.class,例如,System.class 对象 ... -
Map线程安全几种实现方法
2012-06-08 13:10 0如果需要使 Map 线程安 ... -
JAVA国际化
2012-06-08 13:07 1061http://www.cnblogs.com/jjtech/a ... -
JDK动态代理为什么必须针对接口?其与CGLIB的对比02
2012-06-08 12:54 1220http://www.cnblogs.com/fra ... -
JDK动态代理为什么必须针对接口?其与CGLIB的对比01
2012-06-08 12:49 1596http://www.cnblogs.com/frank ... -
cooike 的原理 java
2012-06-08 09:03 1317一 cooike 原理 实际上,Cookie的作用就是与服 ...
相关推荐
Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.
在Java编程语言中,`equals()` 和 `hashCode()` 方法是Object类中的两个核心方法,所有类都默认继承自Object类。这两个方法在处理对象比较和集合操作时起着至关重要的作用。当我们创建自定义类并需要对对象进行精确...
在Java编程语言中,`equals()` 和 `hashCode()` 方法是对象的基本组成部分,它们在很多场景下都发挥着至关重要的作用。这两个方法与对象的相等性比较和哈希表(如HashMap、HashSet)的运作紧密相关。这篇博客将深入...
第二种情况:对于采用哈希算法的集合,集合中对象必须重写 hashCode 方法,同时也要重写 equals 方法。这是因为哈希算法需要使用 hashCode 方法来计算对象的哈希值,而 equals 方法用于判断两个对象是否相等。 如何...
为什么重写equals方法,还必须要重写hashcode方法
Java 中重写 equals() 方法的同时要重写 hashCode() 方法的重要性 在 Java 中,equals() 方法和 hashCode() 方法是两个紧密相关的方法,它们都是用于比较和标识对象的方法。equals() 方法用于比较两个对象的值是否...
例如,在Hashtable、HashMap、HashSet、LinkedHashMap等容器中,我们需要重写hashcode()方法,使其生成对象的哈希码,以便于快速地查找和比较对象。 compareTo()方法是Comparable接口中的一个方法,它用于比较两个...
"Java重写equals及hashcode方法流程解析" Java中的equals和hashCode方法是两个非常重要的方法,它们都是Object...同时,我们还需要注意到,重写equals方法时,必须重写hashCode方法,以便于确保对象的正确性和一致性。
在 Java 中,`equals` 和 `hashCode` 方法是 Object 类中的两个重要方法,它们用于比较对象的相等性。默认情况下,`equals` 方法比较的是两个对象的引用,即是否指向内存中的同一个位置,而 `hashCode` 方法则返回...
#### 二、为什么需要重写equals方法? 1. **提高程序效率**:当两个对象具有相同的业务逻辑上的“身份”时,它们应该被认为是相等的。 2. **增强代码可读性**:重写后的`equals`方法可以根据实际需求来判断对象是否...
现在,让我们深入探讨为什么重写 `equals()` 时要重写 `hashCode()`: 1. **一致性**:一旦对象被创建并赋予了特定的值,其 `equals()` 和 `hashCode()` 方法的结果就应该保持不变,即使在程序的不同执行期间也是...
总结来说,`equals()`和`hashCode()`是Java中用于对象比较和哈希存储的关键方法。它们的正确使用和重写对于确保对象比较的逻辑性和哈希表操作的效率至关重要。在自定义类中,应根据对象的属性和业务逻辑来重写这两个...
在Java编程语言中,`equals()` 和 `hashCode()` 方法是两个非常重要的成员,尤其是在处理对象比较和集合操作时。这两个方法通常与`Object`类中的默认实现相关联,但为了在实际开发中实现正确的对象比较和哈希表操作...
3、**为什么要重写equals()方法?** 默认情况下,`equals()`方法继承自`Object`类,比较的是对象的引用。在处理自定义类时,我们可能关心的是对象的属性是否相等,而不是它们的内存地址。因此,为了基于对象的内容...
"Java中equals、hashcode和==的区别" Java 中 equals、hashcode 和==的区别是 Java 编程语言中一个经常遇到的问题。这三个概念都是用来比较对象的,但是它们之间存在着本质的区别。 首先,==号是Java中的一个...
Java 中的 hashCode 和 equals 方法详解 本文详细介绍了 Java 中的 hashCode 和 equals 方法,探讨了这两个方法的作用、实现机制和使用场景。通过对 hashCode 和 equals 方法的深入分析,我们可以更好地理解 Java ...
为什么在重写 `equals()` 后需要重写 `hashCode()` 呢?假设我们有一个自定义类,并且只重写了 `equals()` 方法。现在,有两个内容相等但内存地址不同的对象,当我们将它们放入 `HashMap` 时,`equals()` 方法可能会...
现在,解释为什么在重写 `equals()` 时通常也要重写 `hashCode()`: 1. **一致性**:根据 Java 的 `Object` 类文档,如果两个对象通过 `equals()` 方法比较为相等,那么它们的 `hashCode()` 方法应该返回相同的值。...
在Java编程中,`equals()` 和 `hashCode()` 方法是Object类中的两个重要方法,它们在处理对象相等性以及在哈希表(如HashSet、HashMap)中起到关键作用。当自定义类时,有时需要根据业务逻辑重写这两个方法以满足...