前言
在java中,每个对象(Object)都有对应的hashcode,hashcode,顾名思义,就是散列的意思,把对象分散存储,哈希(hash)算法将数据依特定算法直接指定到一个地址桶(bucket:一个链表)上,当集合中增加新的元素时,调用这个元素的hashcode()方法,把这个元素定位到它应该放置的桶的位置上。如果这个桶的位置上没有元素,它就可以直接存储在这个桶的位置上;如果这个桶的位置上已经有别的元素,就调用它的equals()方法与新元素进行比较,相同的话就不存了,不相同就散列到其它的地址。
所以,java对eqauls方法和hashCode方法定义如下:
1、如果两个对象相同,那么它们的hashCode值一定要相同;
2、如果两个对象的hashCode相同,两个对象并不一定相同。
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怎么办,例如9除以8和17除以8的余数都是1。这时如何判断呢?在这个时候就需要定义 equals()了。
也就是说,我们先通过hashcode来判断两个对象是否存放某个桶(bucket)里,但这个桶里可能有很多对象,那么我们就需要再通过 equals() 来在这个桶里找我们要的对象。
例如内存中有这样的位置
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怎么办,例如9除以8和17除以8的余数都是1。这时如何判断呢?在这个时候就需要定义 equals()了。
也就是说,我们先通过hashcode来判断两个对象是否存放某个桶(bucket)里,但这个桶里可能有很多对象,那么我们就需要再通过 equals() 来在这个桶里找我们要的对象。
进阶
哈希算法hashCode()是用来产生哈希玛,哈希玛是用来在散列存储结构中确定对象的存储地址,(这一段在 Java编程思想中讲的很清楚的)象util包中的 带 hash 的集合类都是用这种存储结构 :HashMap,HashSet, 他们在将对象存储时(严格说是对象引用),需要确定他们的地址,而HashCode()就是这个用途的,一般都需要重新定义它的,因为默认情况下,由 Object 类定义的 hashCode 方法会针对不同的对象返回不同的整数,这一般是通过将该对象的内部地址转换成一个整数来实现的,现在举个例子来说, 就拿HashSet来说,在将对象存入其中时,通过被存入对象的 hashCode() 来确定对象在 HashSet 中的存储地址,通过equals()来确定存入的对象是否重复,hashCode() ,equals()都需要自己重新定义,因为hashCode()默认前面已经说啦,而equals() 默认是比较的对象引用,你现在想一下,如果你不定义equals()的话,那么同一个类产生的两个内容完全相同的对象都可以存入Set,因为他们是通过 equals()来确定的,这样就使得HashSet 失去了他的意义,看一下下面这个:
哈希算法hashCode()是用来产生哈希玛,哈希玛是用来在散列存储结构中确定对象的存储地址,(这一段在 Java编程思想中讲的很清楚的)象util包中的 带 hash 的集合类都是用这种存储结构 :HashMap,HashSet, 他们在将对象存储时(严格说是对象引用),需要确定他们的地址,而HashCode()就是这个用途的,一般都需要重新定义它的,因为默认情况下,由 Object 类定义的 hashCode 方法会针对不同的对象返回不同的整数,这一般是通过将该对象的内部地址转换成一个整数来实现的,现在举个例子来说, 就拿HashSet来说,在将对象存入其中时,通过被存入对象的 hashCode() 来确定对象在 HashSet 中的存储地址,通过equals()来确定存入的对象是否重复,hashCode() ,equals()都需要自己重新定义,因为hashCode()默认前面已经说啦,而equals() 默认是比较的对象引用,你现在想一下,如果你不定义equals()的话,那么同一个类产生的两个内容完全相同的对象都可以存入Set,因为他们是通过 equals()来确定的,这样就使得HashSet 失去了他的意义,看一下下面这个:
import java.util.*; /** * Description HashSet测试 * 重写equals()和hashcode() * @author usr1999 2014-5-11 */ public class HashSetTest { 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()来比较一下
结果:
[ value = 2, value = 1, value = 3, value = 0]
[ value = 2, value = 1, value = 3, value = 0]
true
false
true
[ value = 2, value = 4, value = 1, value = 3, value = 0]
注释掉hashCode()
[ value = 1, value = 0, value = 2, value = 3]
[ value = 1, value = 0, value = 1, value = 2, value = 3]
false
true
true
[ value = 1, value = 0, value = 1, value = 2, value = 3, value = 4, value = 1]
注释掉equals()
[ value = 2, value = 1, value = 3, value = 0]
[ value = 2, value = 1, value = 1, value = 3, value = 0]
false
true
true
[ value = 2, value = 4, value = 1, value = 1, value = 1, value = 3, value = 0]
总结
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。
(1)当obj1.equals(obj2)为true时,obj1.hashCode() == obj2.hashCode()==true;
(2)当obj1.hashCode() == obj2.hashCode()为false时,obj.equals(obj2)==false。
相关推荐
哈希算法 Hash 哈希算法 Hash 是一种常用的数据加密技术,用于将任意长度的数据转换为固定长度的哈希值。哈希算法 Hash 的设计目的是为了实现数据的加密和身份验证。下面我们将对哈希算法 Hash 进行详细的介绍和...
哈希(Hash)算法在密码学中扮演着至关重要的角色,它是确保数据保密性和完整性的核心工具。哈希算法是一种单向函数,它将任意长度的输入(也称为预映像)转化为固定长度的输出,这个输出被称为哈希值或消息摘要。...
哈希加密算法在信息技术领域扮演着至关重要的角色,它们被广泛应用于数据完整性验证、消息认证码(MAC)、数字签名以及密码存储等方面。本资源提供的是一个C++编写的哈希加密算法函数库,支持多种常见的哈希算法,如...
一致性哈希算法是一种分布式哈希(Distributed Hash Table, DHT)技术,旨在解决在分布式环境中数据分布不均匀的问题。Ketama算法是基于一致性哈希的一种优化实现,由Last.fm公司的Simon Willison提出,其目标是在...
其中,一个被广泛讨论且具有较高学习价值的是暴雪哈希算法(Blizzard Hash Algorithm)。该算法主要应用于处理字符串哈希,特别是在游戏资源管理方面,如文件命名、资源索引等场景中表现出了较高的效率和良好的性能...
在这个压缩包中,我们重点关注的是图像的相似度Hash算法,特别是平均哈希算法(aHash)的Delphi实现。 平均哈希算法(aHash)是一种简化版的图像哈希技术,用于快速比较两幅图像是否大致相同。其基本思想是先将图像...
**感知哈希算法详解与Matlab实现** 感知哈希(Perceptual Hashing,简称pHash)是一种图像识别技术,用于判断两张图片是否相似。它通过模拟人类视觉系统的感知特性,将图片转换成一个简短的哈希值,进而进行比较。...
11283019-吴艳红-实验6 Hash算法.docx很可能是实验报告,其中包含了实验目的、步骤、结果分析以及可能遇到的问题和解决方法。通过阅读这份报告,我们可以深入了解实验过程和哈希算法的理论应用。 S1.txt和S2.txt是...
哈希表算法实现 建哈希表 mid函数先把参数平方,然后取中间的第4、5位作为地址返回
哈希(Hash)算法是一种将任意长度的输入(也叫做预映射)通过一个算法,变换成固定长度的输出,这个输出就是哈希值。哈希函数通常设计为单向的,即给定输入容易得到输出,但给定输出很难找到原始输入。在图像去重...
哈希算法,也称为散列函数,是一种将任意长度的数据转化为固定长度输出的函数。在信息安全、数据验证和数字签名等领域扮演着重要角色。本文主要关注的是如何在8位单片机上实现SHA1哈希算法,这是一种广泛使用的哈希...
标题中的“hash.rar_HASH算法_fpga hash_hash_zebra85v_哈希表Verilog”揭示了这个压缩包文件的主要内容,它涉及到哈希(Hash)算法在高速Field-Programmable Gate Array(FPGA)上的实现,以及与Zebra85v硬件平台和...
哈希算法,也被称为散列函数,是一种在计算领域中广泛应用的数据处理技术。它通过将任意长度的输入(也称为预映射或消息)转换为固定长度的输出,这个输出通常是一个二进制数字,也被称为哈希值或散列码。哈希算法的...
- **哈希表类(Hash Table Class)**:包含哈希表的大小、哈希桶数组以及相关操作(如插入、查找、删除等)的成员函数。 下面是一个简单的C++哈希表实现框架: ```cpp #include #include template , typename ...
弱哈希算法签名的SSL证书(CVE-2004-2761)。 远程服务使用SSL证书链,该证书链已使用加密弱哈希算法(例如MD2、MD4、MD5或SHA1)签名。这些签名算法很容易受到碰撞攻击。攻击者可以利用这一点生成另一个具有相同数字...
在IT领域,哈希算法(Hash Algorithm)是一种用于将任意长度的数据转化为固定长度输出的算法。这个过程通常称为哈希或散列。哈希算法在信息安全、数据完整性验证、密码学等多个方面都有着广泛的应用。本项目是用...
哈希码(Hash Code)是一种在计算机科学中广泛使用的数据处理技术,主要应用于查找和存储。标题中的"hash code"指的是这种技术,特别是在Java中的`Hashtable`类中的应用。哈希函数是哈希码的核心,它能够将任意大小...
哈希查找算法是一种在计算机科学中广泛使用的数据结构和算法技术,它主要依赖于哈希函数来实现快速的查找操作。哈希函数是将输入(通常是一个字符串或对象)映射到一个固定大小的数值(通常是一个数组的索引)的过程...
暴雪哈希(Blizzard Hash)算法是一种由暴雪娱乐公司设计的独特哈希函数,它在计算机科学领域,特别是信息安全和数据处理中占有重要地位。这个算法因其高效性和优秀的抗冲突性能而备受赞誉。哈希算法是将任意长度的...