`
jianchen
  • 浏览: 344778 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

【转】hashCode()的作用

阅读更多

http://blog.csdn.net/badboy_blue/archive/2009/01/06/3720509.aspx

1.hashcode是用来查找的,如果你学过数据结构就应该知道,在查找和排序这一章有 
例如内存中有这样的位置 
0 1 2 3 4 5 6 7 
而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,如果不用hashcode而任意存放,那么当查找时就需要到这八个位置里挨个去找,或者用二分法一类的算法。 
但如果用hashcode那就会使效率提高很多。 
我 们这个类中有个字段叫ID,那么我们就定义我们的hashcode为ID%8,然后把我们的类存放在取得得余数那个位置。比如我们的ID为9,9除8的余 数为1,那么我们就把该类存在1这个位置,如果ID是13,求得的余数是5,那么我们就把该类放在5这个位置。这样,以后在查找该类时就可以通过ID除8 求余数直接找到存放的位置了。

2.但是如果两个类有相同的hashcode怎么办那(我们假设上面的类的ID不是唯一的),例如9除以8和17除以8的余数都是1,那么这是不是合法的,回答是:可以这样。那么如何判断呢?在这个时候就需要定义 equals了。 
也就是说,我们先通过 hashcode来判断两个类是否存放某个桶里,但这个桶里可能有很多类,那么我们就需要再通过 equals 来在这个桶里找到我们要的类。 
那么。重写了equals(),为什么还要重写hashCode()呢? 
想想,你要在一个桶里找东西,你必须先要找到这个桶啊,你不通过重写hashcode()来找到桶,光重写equals()有什么用啊 
3。你要对A类排序,有两种方法,一种就是让A类实现comparabole结构并实现compareTo()方法,那么可以通过Collections.sort(List <A> list)对其进行排序 
另一种方法:自己定义一个类B实现Comparator类并实现compare方法, 
然后通过Collections.sort(List <A> list,B b)进行排序

hashCode() 是用来产生哈希玛的,而哈希玛是用来在散列存储结构中确定对象的存储地址的,(这一段在 Java编程思想 中讲的很清楚的)象util包中的 带 hash 的集合类都是用这种存储结构 :HashMap,HashSet, 他们在将对象存储时(严格说是对象引用),需要确定他们的地址吧, 而HashCode()就是这个用途的,一般都需要重新定义它的,因为默认情况下,由 Object 类定义的 hashCode 方法会针对不同的对象返回不同的整数,这一般是通过将该对象的内部地址转换成一个整数来实现的,现在举个例子来说, 就拿HashSet来说 ,在将对象存入其中时,通过被存入对象的 hashCode() 来确定对象在 HashSet 中的存储地址,通过equals()来确定存入的对象是否重复,hashCode() ,equals()都需要自己重新定义,因为hashCode()默认前面已经说啦,而equals() 默认是比较的对象引用,你现在想一下,如果你不定义equals()的话,那么同一个类产生的两个内容完全相同的对象都可以存入Set,因为他们是通过 equals()来确定的,这样就使得HashSet 失去了他的意义,看一下下面这个: 

public class Test { 
public static void main(String[] args) { 
HashSet set = new HashSet(); 
for (int i = 0; i <= 3; i++){ 
set.add(new Demo1(i,i)); 
}
System.out.println(set);
set.add(new Demo1(1,1)); 
System.out.println(set);
System.out.println(set.contains(new Demo1(0,0))); 
System.out.println(set.add(new Demo1(1,1))); 
System.out.println(set.add(new Demo1(4,4))); 
System.out.println(set);
}

private static class Demo1 { 
private int value; 

private int id; 

public Demo1(int value,int id) { 
this.value = value; 
this.id=id; 
}

public String toString() { 
return " value = " + value; 
}

public boolean equals(Object o) { 
Demo1 a = (Demo1) o;
return (a.value == value) ? true : false; 
}

public int hashCode() { 
return id; 
}
}
}

你分别注释掉hashCode()和 equals()来比较一下他们作用就可以拉,关键要自己动手看看比较的结果你就可以记得很清楚啦

如果还不是很明确可以再看另一个例子:


public final class Test { 

public static void main(String[] args) { 
Map m = new HashMap(); 
m.put(new PhoneNumber(020, 12345678), "shellfeng"); 
System.out.println(m.get(new PhoneNumber(020, 12345678))); 
}

private static class PhoneNumber { 
/**
* 区号
*/
private short areaCode; 

/**
* 扩展号
*/
private short extension; 

public PhoneNumber(int areaCode, int extension) { 
this.areaCode = (short) areaCode; 
this.extension = (short) extension; 
}

public boolean equals(Object o) { 
if (o == this) { 
return true; 
}
if (!(o instanceof PhoneNumber)) { 
return false; 
}
PhoneNumber pn = (PhoneNumber) o;
return pn.extension == extension && pn.areaCode == areaCode; 
}

/**
* @see java.lang.Object#hashCode()
* @return result就是我们得到的散列值,其实我们的计算过程可以多种,这里只不过是一个例子,需要你的灵活运用,使其接近你需要的理想结果
*/
public int hashCode() { 
int result = 17; 
result = 37 * result + areaCode; 
result = 37 * result + extension; 
return result; 
}
}
}

 
还是那句话:你注释掉hashCode()比较一下他们作用就可以拉,关键要自己动手看看比较的结果你就可以记得很清楚啦

总结
hashCode() 方法使用来提高Map里面的搜索效率的,Map会根据不同的hashCode()来放在不同的桶里面,Map在搜索一个对象的时候先通过 hashCode()找到相应的桶,然后再根据equals()方法找到相应的对象.要正确的实现Map里面查找元素必须满足一下两个条件: 
(1)当obj1.equals(obj2)为true时obj1.hashCode() == obj2.hashCode()必须为true 
(2)当obj1.hashCode() == obj2.hashCode()为false时obj.equals(obj2)必须为false

Java中的集合(Collection)有两类,一类是List,再有一类是Set。你知道它们的区别吗?前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。
那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。
但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。
也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。
哈 希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。我们可以认为hashCode方法返回的就是对象存储的物理地址(实际可能并不是,例 如:通过获取对象的物理地址然后除以8再求余,余数几是计算得到的散列值,我们就认为返回一个不是物理地址的数值,而是一个可以映射到物理地址的值)。
这 样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直 接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列 其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。

分享到:
评论

相关推荐

    HashCode的用法详解

    hashCode 的作用 hashCode 的主要作用是用于查找和排序。在查找和排序的过程中,我们需要快速地定位到目标对象,而 hashCode 正是这个过程的关键。例如,在内存中有 8 个位置,分别是 0 1 2 3 4 5 6 7,我们可以...

    hashcode和equals的分析

    该方法的主要作用是返回一个整数,这个整数通常被用来作为哈希表中元素的索引。 #### 1.1 哈希算法简介 哈希算法是一种将任意长度的数据映射为固定长度的算法。简单来说,哈希算法就是将输入数据转换为一个特定的...

    java中hashcode和equals的详解.pdf

    本文详细介绍了 Java 中的 hashCode 和 equals 方法,探讨了这两个方法的作用、实现机制和使用场景。通过对 hashCode 和 equals 方法的深入分析,我们可以更好地理解 Java 集合的实现原理和哈希表的工作机制。 一、...

    深入理解Java中HashCode方法

    Java中的hashCode方法是每个类都需要实现的重要方法之一,它的主要作用是将对象的数据转换为一个32位的整数,用于标识对象的唯一性。在Java的所有类中,Object类是最顶层的父类,它定义了hashCode方法,该方法返回...

    equals 和 hashCode两者效果分析详解.docx

    接下来,我们将详细探讨它们的作用、关系以及在实际开发中的应用。 首先,`equals()`方法是Java中用来判断两个对象是否逻辑相等的。当我们说两个对象逻辑相等,意味着它们具有相同的属性和状态,即使它们在内存中的...

    关于Object中equals方法和hashCode方法判断的分析

    "关于Object中equals方法和hashCode方法判断...equals 和 hashCode 方法都是用于比较两个对象是否相同的,但它们的实现机理和作用域却有所不同。通过重写这两个方法,我们可以更好地比较对象的内容,并避免对象的重复。

    超详细_解释java_equals()与hashCode().pdf

    在Java编程中,`equals()`和`hashCode()`方法是Object类中的两个重要方法,它们在比较和处理对象时起着至关重要的作用。`equals()`方法用于判断两个对象是否相等,而`hashCode()`方法则与对象在哈希表中的存储位置...

    java中hashcode()和equals()的详解.docx

    - **`hashCode()`方法的作用**:当向哈希表中插入新对象时,Java会先调用该对象的`hashCode()`方法来确定其存储位置。如果该位置为空,则直接存放对象;如果该位置已有对象,则进一步调用`equals()`方法判断新旧对象...

    Java中的hashcode方法介绍

    Java中的`hashCode`方法是Java编程语言中的一个重要概念,它主要与对象的散列处理相关。在Java的`Object`类中定义了一个本地方法(native)`hashCode()`,该方法返回一个`int`类型的数值。这个数值是根据对象的状态...

    hashcode-2k21:我们团队的HashCode 2k21解决方案的仓库

    哈希码(HashCode)的名字来源于计算机科学中的哈希函数,这是一种将任意大小的数据映射为固定大小输出(通常为整数)的函数,它在数据结构如哈希表和分布式计算中起着关键作用。 【哈希函数】是此竞赛中的重要概念...

    对象转型和多态1

    在Java编程语言中,对象转型和多态是面向对象编程的重要概念,它们在软件设计和实现中发挥着关键作用。本文将深入探讨Object类、对象转型(向上转型和向下转型)以及多态的概念。 **第一节: Object类** Object类...

    我怀疑这是IDEA的BUG,但是我翻遍全网没找到证据!.doc

    1.Lombok @Data 注解的作用和原理:Lombok 的 @Data 注解可以生成类的无参构造函数、get/set 方法、equals 方法、toStrong 方法和 hashCode 方法等。它通过字节码增强技术,直接操作字节码文件来实现这些功能。 2. ...

    java2022面试宝典

    八、HashCode的作用 在Java集合中,特别是Set接口的实现,如HashSet,使用哈希算法来存储和查找元素。通过对象的hashCode(),Set可以快速定位元素位置,提高查找效率。如果两个对象equals()相等,它们的hashCode()...

    Java高新技术Java高新技术.doc

    Java高新技术涵盖了许多关键概念,这些概念在现代软件开发中起着至关重要的作用。以下是一些主要知识点的详细说明: 1. **静态导入**:在Java中,`import static`关键字允许我们直接使用类中的静态成员,而无需通过...

    java程序员面试整理3(1).pdf

    hashCode() 方法返回一个对象的哈希码,而 equals() 方法比较两个对象的实际值是否相等。 十五、自动拆装箱 自动拆装箱是 Java 中的一种机制,它可以自动将基本类型转换为对应的包装类型,反之亦然。但是,自动拆...

    java开发常用的jar包的作用解释.pdf

    Java 开发常用的 jar 包的作用解释 Java 开发中,jar 包是不可或缺的一部分。jar 包可以提供各种功能,例如 IO 操作、反射和自省、字符串操作、数学运算等等。在本文中,我们将对常用的 jar 包进行详细的解释。 1....

    oracle-mooc-lambdas-streams-quiz1-question9:演示了针对Lambda和Streams上的Oracle MOOC的测验1中问题9的问题

    l.replace(Integer::hashCode) l.replace(n -&gt; n.hashCode()) l.replaceAll(Integer::hashCode) l.replaceAll(n -&gt; n.hashCode()) l.replaceAll(Number::hashCode) 可能答案的顺序是随机的,并且每次参加测验时都会...

    spring 自定义属性编辑器

    当我们需要将字符串形式的数据转换为Java对象时,属性编辑器就发挥了关键作用。例如,从请求参数或配置文件中读取的字符串可能需要转换为日期、颜色代码或其他自定义类型。这篇博客“spring 自定义属性编辑器”可能...

    标签使用

    - **converter的作用**:主要负责数据类型的转换工作,即将表单域中的数据类型转换为JavaBean中的数据类型,反之亦然。 - **未指定converter的影响**:如果在使用`&lt;rich:listShuttle&gt;`时没有正确设置`converter`属性...

    BTA 常问的 Java基础39道常见面试题及详细答案.docx

    9. **HashMap的hashcode作用**: 在HashMap中,hashCode用于计算存储位置,重写hashCode方法可以优化哈希表的性能,避免哈希冲突。 10. **ArrayList、LinkedList、Vector的区别**: - ArrayList基于动态数组,...

Global site tag (gtag.js) - Google Analytics