HASH:

Hash是散列的意思,就是把任意长度的输入,通过散列算法变换成固定长度的输出,该输出就是散列值。关于散列值,有以下几个关键结论:

1、如果散列表中存在和散列原始输入K相等的记录,那么K必定在f(K)的存储位置上

2、不同关键字经过散列算法变换后可能得到同一个散列地址,这种现象称为碰撞

3、如果两个Hash值不同(前提是同一Hash算法),那么这两个Hash值对应的原始输入必定不同

几种常见的hash算法:

(1) MD4

  MD4(RFC 1320)是 MIT 的 Ronald L. Rivest 在 1990 年设计的,MD 是 Message Digest 的缩写。它适用在32位字长的处理器上用高速软件实现--它是基于 32 位操作数的位操作来实现的。

(2) MD5

  MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好

(3) SHA-1 及其他

  SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。

equals的使用:

在Java语言中,equals方法在使用时

针对包装对象,比较的是对象的值(包括 boolean,byte,char,short,int,long,float,double)

针对String对象,比较的也是String的值(因为String内部重写了equals方法和hashCode方法)

针对其他object对象,比较的是两个对象的引用是否指向同一个内存地址

hashcode:

1、HashCode的存在主要是为了查找的快捷性,在对象存储的散列表里面,hashCode用来指定对象存储的内存地址。而equals用来判断对象的引用是否指向同一个地址,也就是判断两个对象的hashCode值是否一致

2、如果两个对象equals相等,那么这两个对象的HashCode一定也相同

3、如果对象的equals方法被重写,那么对象的HashCode方法也尽量重写

4、如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置

再归纳一下就是hashCode是用于查找使用的,而equals是用于比较两个对象的是否相等的。

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规定,如果两个类的HashCode都不相同,那么这两个类必定是不同的。用在hashset结构中,就可以大大减少实际调用equals方法的次数,提高效率。
但是如果两个类有相同的hashcode怎么办那(我们假设上面的类的ID不是唯一的),例如9除以8和17除以8的余数都是1,那么这是不是合法的,回答是:可以这样。那么如何判断呢?在这个时候就需要定义 equals了。
也就是说,我们先通过 hashcode来判断两个类是否存放某个桶里,但这个桶里可能有很多类,那么我们就需要再通过 equals 来在这个桶里找到我们要的类。
那么。重写了equals(),为什么还要重写hashCode()呢?
想想,你要在一个桶里找东西,你必须先要找到这个桶啊,你不通过重写hashcode()来找到桶,光重写equals()有什么用啊

  为什么重写Object的equals(Object obj)方法尽量要重写Object的hashCode()方法?

具体事例:

public class HashTest {
private int i; public int getI() {
return i;
} public void setI(int i) {
this.i = i;
} public int hashCode() {
return i % 10;
} public final static void main(String[] args) {
HashTest a = new HashTest();
HashTest b = new HashTest();
a.setI(1);
b.setI(1);
Set<HashTest> set = new HashSet<HashTest>();
set.add(a);
set.add(b);
System.out.println(a.hashCode() == b.hashCode());
System.out.println(a.equals(b));
System.out.println(set);
}
}

  输出结果:

true
false
[com.ubs.sae.test.HashTest@1, com.ubs.sae.test.HashTest@1]

  以上这个示例,我们只是重写了hashCode方法,从上面的结果可以看出,虽然两个对象的hashCode相等,但是实际上两个对象并不是相等;,我们没有重写equals方法,那么就会调用object默认的equals方法,是比较两个对象的引用是不是相同,显示这是两个不同的对象,两个对象的引用肯定是不定的。这里我们将生成的对象放到了HashSet中,而HashSet中只能够存放唯一的对象,也就是相同的(适用于equals方法)的对象只会存放一个,但是这里实际上是两个对象a,b都被放到了HashSet中,这样HashSet就失去了他本身的意义了。

此时我们把equals方法给加上:

public class HashTest {
private int i; public int getI() {
return i;
} public void setI(int i) {
this.i = i;
} <span style="color:#3366FF;"><strong>public boolean equals(Object object) {
if (object == null) {
return false;
}
if (object == this) {
return true;
}
if (!(object instanceof HashTest)) {
return false;
}
HashTest other = (HashTest) object;
if (other.getI() == this.getI()) {
return true;
}
return false;
}</strong></span> public int hashCode() {
return i % 10;
} public final static void main(String[] args) {
HashTest a = new HashTest();
HashTest b = new HashTest();
a.setI(1);
b.setI(1);
Set<HashTest> set = new HashSet<HashTest>();
set.add(a);
set.add(b);
System.out.println(a.hashCode() == b.hashCode());
System.out.println(a.equals(b));
System.out.println(set);
}
}

  此时得到的结果就会如下:

true
true
[com.ubs.sae.test.HashTest@1]

  从结果我们可以看出,现在两个对象就完全相等了,HashSet中也只存放了一份对象。

关于String的hashCode方法

要注意的是,String重写了hashCode方法。这是因为散列表(hash表)操作中费时多的部分就是计算hashCode方法,所以在String类中的hashCode方法包含一个重要的优化:每个String对象内部都存储了它的hashCode值,该值初始为0,但如果hashCode方法被调用,那么这个值就将会被记住,下一次使用的时候可以直接调用出来,而不用再计算一次。之所以能这样实现,是由于String类是不可改变的。所以hashCode值被计算之后也并不会发生变化。

String类的hashCode的实现,简要摘录如下:

public final class String{  

    private int hash = 0;  

    public int hashCode(){
if(hash != 0){
return hash;
} for(int i=0; i<length(); i++){
hash = hash * 31 + (int) charAt(i);
}
return hash;
}
}

  

谈谈hashcode和equals的用法的更多相关文章

  1. hashCode()和equals()的用法

    使用hashCode()和equals() hashCode()和equals()定义在Object类中,这个类是所有java类的基类,所以所有的java类都继承这两个方法. hashCode()方法 ...

  2. Java 中正确使用 hashCode 和 equals 方法

    在这篇文章中,我将告诉大家我对hashCode和equals方法的理解.我将讨论他们的默认实现,以及如何正确的重写他们.我也将使用Apache Commons提供的工具包做一个实现. 目录: hash ...

  3. (转)Java 中正确使用 hashCode 和 equals 方法

    背景:最近在编写持久化对象时候遇到重写equals和hashCode方法的情况,对这两个方法的重写做一个总结. 链接:https://www.oschina.net/question/82993_75 ...

  4. Java中正确使用hashCode和equals方法

    在这篇文章中,我将告诉大家我对hashCode和equals方法的理解.我将讨论他们的默认实现,以及如何正确的重写他们.我也将使用Apache Commons提供的工具包做一个实现. 目录: hash ...

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

    今天下午研究了半天hashcode()和equals()方法,终于有了一点点的明白,写下来与大家分享(zhaoxudong 2008.10.23晚21.36). 1. 首先equals()和hashc ...

  6. 使用hashCode()和equals()方法 - Java

    在这篇文章中,我将指出我对hashCode()和equals()方法的理解.我将讨论它们的默认实现以及如何正确地覆盖它们.我还将使用Apache Commons包中的实用工具类来实现这些方法. has ...

  7. JAVA基础4——谈谈HashCode与HashMap相关概念

    谈谈HashCode与HashMap HashCode hashCode,即一个Object的散列码. HashCode的作用: 对于List.数组等集合而言,HashCode用途不大: 对于Hash ...

  8. hashcode、equals和 ==详解

    两个对象值相同(x.equals(y) == true),则一定有相同的hash code: 这是java语言的定义: 因为:Hash,一般翻译做“散列”,也有直接音译为"哈希"的 ...

  9. 对hashcode、equals的理解

    1.首先hashcode和equals都是java每个对象都存在的方法,因为他们两是Object的方法. 2.hashcode方法默认返回的是该对象内存地址的哈希码,然而你会发现,Object类中没有 ...

随机推荐

  1. java代码行数统计工具类

    package com.syl.demo.test; import java.io.*; /** * java代码行数统计工具类 * Created by 孙义朗 on 2017/11/17 0017 ...

  2. Memcached 查询stats及各项状态解释

    一.两个最常用状态查询(掌握第一个就完全OK了) 1)查看状态:printf “stats\r\n” |nc 127.0.0.1 11211      2)模拟top命令查看状态:watch “ech ...

  3. Firebird 列可空非空修改

    2018-12-04 至少到Firebird 3.0.4 已经添加了设置可空 和 非空的语法:如 -- 删除非空(设置为可空) ALTER TABLE TECH ALTER label drop NO ...

  4. SQL Server 2008中的MERGE(数据同步)

    OK,就像标题呈现的一样,SQL Server 2008中的MERGE语句能做很多事情,它的功能是根据源表对目标表执行插入.更新或删除操作.最典型的应用就是进行两个表的同步. 下面通过一个简单示例来演 ...

  5. C++(笔)002

    #include <iostream> //预处理器编译指令 int main() //函数头:对函数和程序其它部份之间的接口作出总结 int:函数的返回类型 { using namesp ...

  6. node.js缓存处理方式

    Node.JS缓存处理分为客户端和服务端两个部分. 客户端的缓存主要是利用浏览器对HTTP协议响应头中cache-control和expires字段的支持.浏览器在得到明确的响应头后,会将文件缓存在本 ...

  7. JS读取粘贴板内容

    1.1     监听onpaste事件 1.1.1 定义和用法 npaste 事件在用户向元素中粘贴文本时触发. 注意: 虽然使用的 HTML 元素都支持 onpaste 事件,但实际上并非支持所有元 ...

  8. UX2内核浏览加速技术纲要[带你解决WebView卡顿]

    UX2内核是本人负责主要开发的浏览服务项目,其主要目的是为开发者提供一个简单好用.轻便的网络浏览服务.UX2内核的安卓端是基于WebView进行深度优化的,同时欢迎大家使用这个内核用于app页面或浏览 ...

  9. Sql-exec

    --显示sql server现有的所有数据库 exec sp_helpdb --查看数据表设置的约束 exec sp_helpconstraint SubjectType --update selec ...

  10. C++ VS编译问题--VS下生成DLL,但没有生成Lib的解决办法

    如果项目生成了.dll文件,但是没有生成.lib文件,这是由于项目的设置错误,应作如下修改: 项目->属性->链接器->输入->模块定义文件,设置你的模块定义文件,默认为lib ...