精华内容
下载资源
问答
  • 哈希表就是 依据关键字可以根据一定的算法(哈希函数)映射到表中特定位置 思想建立表。因此哈希表最大特点就是可以根据f(K)函数得到其在数组中索引。 接下来来看看Java中Object对hashCod...
        

    由表及里,循序渐进,请往下看。随手点赞是对作者最大的鼓励!^0^。

    什么是哈希表

    引用:严蔚敏 《数据结构(C语言版)》中的内容 严蔚敏 《数据结构(C语言版)》 截图

    哈希表就是 依据关键字可以根据一定的算法(哈希函数)映射到表中的特定位置 的思想建立的表。因此哈希表最大的特点就是可以根据f(K)函数得到其在数组中的索引。

    接下来来看看Java中Object对hashCode()方法的说明,当然此方法和equals(Object obj)方法是相辅相成的。

    Object类中的equals和hashCode方法(文章内源码均基于JDK8)

    equals方法官方文档:

    public boolean equals(Object obj)

    Indicates whether some other object is "equal to" this one.

    The equals method implements an equivalence relation on non-null
    object references:

    · It is reflexive: for any non-null reference value x, x.equals(x) should return true.
    · It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
    · It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
    · It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
    · For any non-null reference value x, x.equals(null) should return false.

    The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

    Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

    Parameters:
    obj the reference object with which to compare.
    Returns:
    true if this object is the same as the obj argument; false otherwise.
    See Also:
    hashCode(),java.util.HashMap

    在官方说明中,指明了equals方法具有自反性、对称性、传递性、一致性,同时也提醒在在继承Object的时候,如果要重写hashCode方法,通常都需要重写该方法,因为hashCode要求(下面也有提及):如果两个对象执行equals方法结果为true,则两对象的哈希码应该是相等的。

    hashCode方法官方文档:

    public native int hashCode();

    Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by java.util.HashMap.

    The general contract of hashCode is:

    · Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
    · If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
    · It is not required that if two objects are unequal according to the java.lang.Object.equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
    As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java™ programming language.)
    Returns:
    a hash code value for this object.
    See Also:
    java.lang.Object.equals(java.lang.Object),java.lang.System.identityHashCode

    该方法返回对象的经过处理后的内存地址,由于每个对象的内存地址都不一样,所以哈希码也不一样。此方法为native方法,取决于JVM的内部设计,一般是某种C地址的偏移。

    文档中给出了三条规定:

    1. 在对象没有被修改的前提下,执行多次调用,该hashCode方法必须始终返回相同的整数。
    2. 如果两个对象执行equals方法结果为true,则分别调用hashCode方法产生的整数结果是相等的。
    3. 非必要要求:两个对象执行equals方法结果为false,则分别调用hashCode方法产生的整数结果是不相等的。

    第三个要求虽然为非必需,但如果实现,则可以提高散列表的性能。

    接下来分析几个常见的实现方式。

    String的equals和hashCode方法

    • hashCode方法源码:
        public int hashCode() {
            int h = hash;
            if (h == 0 && value.length > 0) {
                char val[] = value;
    
                for (int i = 0; i < value.length; i++) {
                    h = 31 * h + val[i];
                }
                hash = h;
            }
            return h;
        }

    该函数很简单,以31为权,每一位为字符的ASCII值进行运算,用自然溢出来等效取模,达到了目的——只要字符串的内容相同,返回的哈希码也相同。但是乘子31在此需要解释一下。选31作为乘子,是因为:

    1. 31是一个奇质数,如果选择一个偶数会在乘法运算中产生溢出,导致数值信息丢失,因为乘二相当于移位运算。选择质数的优势并不是特别的明显,但这是一个传统。
    2. 31可以被JVM优化:31 * i = (i << 5) - i。
    • equals方法源码:
        public boolean equals(Object anObject) {
            if (this == anObject) {
                return true;
            }
            if (anObject instanceof String) {
                String anotherString = (String)anObject;
                int n = value.length;
                if (n == anotherString.value.length) {
                    char v1[] = value;
                    char v2[] = anotherString.value;
                    int i = 0;
                    while (n-- != 0) {
                        if (v1[i] != v2[i])
                            return false;
                        i++;
                    }
                    return true;
                }
            }
            return false;
        }

    此equals方法包含了"==",双等号比较的是地址,存储地址相同,内容则相同。当地址不同的时候,先验证了比较对象是否为String,接着比较了两个字符串的长度,最后才循环比较每个字符是否相等。

    Integer的equals和hashCode方法

    • hashCode方法源码:
        @Override
        public int hashCode() {
            return Integer.hashCode(value);
        }
        public static int hashCode(int value) {
            return value;
        }
    • equals方法源码:
         public boolean equals(Object obj) {
            if (obj instanceof Integer) {
                return value == ((Integer)obj).intValue();
            }
            return false;
        }

    由此可见,Integer哈希码就是Integer对象里所包含的那个整数的数值,且equals方法比较的也是两者的整数数值,即两个数值大小的Integer对象,计算出的哈希码是相等的。

    最后,像int,char这样的基础类,它们不需要hashCode,如果需要存储时,将进行自动装箱操作,计算方法同Integer。

    哈希碰撞(hash冲突)

    在计算hash地址的过程中会出现对于不同的关键字出现相同的哈希地址的情况,即key1 ≠ key2,但是f(key1) = f(key2),这种情况就是Hash 冲突。具有相同关键字的key1和key2称之为同义词。
    通过优化哈希函数可以减少这种冲突的情况(如:均衡哈希函数),但是在通用条件下,考虑到于表格的长度有限及关键值(数据)的无限,这种冲突是不可避免的,所以就需要处理冲突。

    冲突处理

    冲突处理分为以下四种方式:

    1. 开放地址
    2. 再哈希
    3. 链地址
    4. 建立公共溢出区

    其中开放地址又分为:

    • 线性探测再散列
    • 二次探测再散列
    • 伪随机探测再散列

    下面谈谈几种方法的原理:

    开放地址

    开放地址法处理冲突的基本原则就是出现冲突后按照一定算法查找一个空位置存放。公式:
    clipboard.png
    Hi为计算出的地址,H(key)为哈希函数,di为增量。其中di的三种获取方式既是上面提到的开放地址法的三种分类(线性探测再散列、二次探测再散列、伪随机探测再散列)。

    • 线性探测再散列
      clipboard.png
      ,即依次向后查找。
    • 二次探测再散列
      clipboard.png,即依次向前后查找,增量为1、2、3的二次方。
    • 伪随机探测再散列
      伪随机,顾名思义就是随机产生一个增量位移。

    再哈希法

    再哈希法,就是出现冲突后采用其他的哈希函数计算,直到不再冲突为止。

    clipboard.png,其中RHi为不同的哈希函数。

    链地址法

    链接地址法不同与前两种方法,他是在出现冲突的地方存储一个链表,所有的同义词记录都存在其中。形象点说就行像是在出现冲突的地方直接把后续的值摞上去。例如HashMap,如下图。

    clipboard.png

    建立公共溢出区

    建立公共溢出区的基本思想是:假设哈希函数的值域是[1,m-1],则设向量HashTable[0...m-1]为基本表,每个分量存放一个记录,另外设向量OverTable[0...v]为溢出表,所有关键字和基本表中关键字为同义词的记录,不管它们由哈希函数得到的哈希地址是什么,一旦发生冲突,都填入溢出表。

    展开全文
  • 散列算法

    千次阅读 2020-02-28 12:02:00
    散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的 数据,常见的散列算法如 MD5、SHA 等。一般进行散列时最好提供一个 salt(盐),比如 加密密码“admin”,产生的散列值是“21232f...

    散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的 数据,常见的散列算法如 MD5、SHA 等。一般进行散列时最好提供一个 salt(盐),比如 加密密码“admin”,产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,可以到一 些 md5 解密网站很容易的通过散列值得到密码“admin”,即如果直接对密码进行散列相 对来说破解更容易,此时我们可以加一些只有系统知道的干扰数据,如用户名和 ID(即盐); 这样散列的对象是“密码+用户名+ID”,这样生成的散列值相对来说更难破解。

    散列时还可以指定散列次数,如 2 次表 示:md5(md5(str)):“new Md5Hash(str, salt, 2).toString()”

     

    展开全文
  • shiro的散列算法和凭证配置

    千次阅读 2020-12-24 13:11:00
    散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),比如 加密密码“admin”,产生的散列值是“21232f297...

    1,散列算法概述

    散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),比如

    加密密码“admin”,产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,可以到一

    些md5 解密网站很容易的通过散列值得到密码“admin”,即如果直接对密码进行散列相

    对来说破解更容易,此时我们可以加一些只有系统知道的干扰数据,如用户名和ID(即盐);

    这样散列的对象是“密码+用户名+ID”,这样生成的散列值相对来说更难破解。

    2,MD5算法

    public class ShiroTest {
     //shiro提供了现成的加密类 Md5Hash
     @Test
     public void testMd5(){
      //MD5加密
      String password = new Md5Hash("1111").toString();
      System.out.println("加密后:"+password);
      //加盐 salt 默认一次散列
      String password_salt=new Md5Hash("1111", "laolei").toString();
      System.out.println("加盐后:"+password_salt);
      //散列2次
      String password_salt_2 = new Md5Hash("1111", "laolei", 2).toString();
      System.out.println("散列2次:"+password_salt_2);
      //使用SimpleHash
      SimpleHash hash = new SimpleHash("MD5", "1111", "laolei", 2);
      System.out.println("simpleHash:"+hash.toString());
     }
    }
    

    3,在自定义Realm中使用散列

    Realm实现代码

    public class UserRealm extends AuthorizingRealm {
     @Override
     public String getName() {
      return "UserRealm";
     }
     //用于认证
     @Override
     protected AuthenticationInfo doGetAuthenticationInfo(
       AuthenticationToken token) throws AuthenticationException {
      //从token中获取身份信息
      String username = (String)token.getPrincipal();
      //根据用户名到数据库中取出用户信息 如果查询不到 返回null
      //按照固定规则加密码结果 ,此密码 要在数据库存储,原始密码 是1111,盐是laolei 2次散列
      String password = "1620d20433da92e2523928e351e90f97";//假如从数据库中获取密码为1111 
      //返回认证信息
      SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,  
        password, ByteSource.Util.bytes("laolei"),this.getName());
      return simpleAuthenticationInfo;
     }
     //用于授权
     @Override
     protected AuthorizationInfo doGetAuthorizationInfo(
       PrincipalCollection principals) {
      return null;
     }
    }
    

    4, Realm配置

    Shiro.ini 在配置文件中,需指定凭证匹配器

    [main]
    #定义凭证匹配器
    credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
    #散列算法
    credentialsMatcher.hashAlgorithmName=md5
    #散列次数
    credentialsMatcher.hashIterations=2
    #将凭证匹配器设置到realm
    userRealm=com.sxt.realm.UserRealm
    userRealm.credentialsMatcher=$credentialsMatcher
    securityManager.realms=$userRealm
    

    5, 测试

    public static void main(String[] args) {
    		//得到工厂
    		Factory&lt;SecurityManager&gt; factory=new IniSecurityManagerFactory();
    		//创建SecurityManager
    		SecurityManager securityManager=factory.getInstance();
    		//把SecurityManager绑定到运行环境
    		SecurityUtils.setSecurityManager(securityManager);
    		//创建主体
    		Subject subject=SecurityUtils.getSubject();
    		//创建Token用于验证
    		UsernamePasswordToken token=new UsernamePasswordToken("zhangsan", "123");
    		try {
    			//认证
    			subject.login(token);
    			System.out.println(subject.isAuthenticated());
    		} catch (UnknownAccountException e) {
    			System.out.println("用户名不存在");
    		}catch (IncorrectCredentialsException e) {
    			System.out.println("密码不正确");
    		}
    	}
    
    展开全文
  • Shiro-散列算法

    2018-04-18 14:36:32
    散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),比如加密密码“admin”,产生的散列值是“21232f297...

    Shiro-散列算法

    5.2 散列算法 (SHA)

    散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),比如加密密码“admin”,产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,可以到一些md5解密网站很容易的通过散列值得到密码“admin”,即如果直接对密码进行散列相对来说破解更容易,此时我们可以加一些只有系统知道的干扰数据,如用户名和ID(即盐);这样散列的对象是“密码+用户名+ID”,这样生成的散列值相对来说更难破解。

    Java代码  收藏代码
    1. String str = "hello";  
    2. String salt = "123";  
    3. String md5 = new Md5Hash(str, salt).toString();//还可以转换为 toBase64()/toHex()   

    如上代码通过盐“123”MD5散列“hello”。另外散列时还可以指定散列次数,如2次表示:md5(md5(str)):“new Md5Hash(str, salt, 2).toString()”。

      

    Java代码  收藏代码
    1. String str = "hello";  
    2. String salt = "123";  
    3. String sha1 = new Sha256Hash(str, salt).toString();   

    使用SHA256算法生成相应的散列数据,另外还有如SHA1、SHA512算法。     

     

    Shiro还提供了通用的散列支持:

    Java代码  收藏代码
    1. String str = "hello";  
    2. String salt = "123";  
    3. //内部使用MessageDigest  
    4. String simpleHash = new SimpleHash("SHA-1", str, salt).toString();   

    通过调用SimpleHash时指定散列算法,其内部使用了Java的MessageDigest实现。


    展开全文
  • 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),如:对密码进行加密,用户名和ID(盐);这样散列的对象是...
  • 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法有MD5,SHA等。一般进行散列时最好提供一个salt(盐),比如 使用MD5加密后的结果:e10adc3949ba59abbe56e057f20...
  • 目前常见的散列(Hash)算法 算法名称 输出大小(bits) 内部大小 区块大小 长度大小 字符尺寸 碰撞情形 HAVAL 256/224/192/160/128 256 1024 64 32 是 MD2 128 384 128 No 8 大多数 MD4 128 128 512 64 ...
  • 02 散列算法

    2020-02-04 12:05:33
    散列算法 1 简介 它典型应用是对一段信息产生信息摘要。 2 常见算法 2.1 MD5算法 MD5用是哈希函数,它典型应用是对一段信息产生信息摘要,以防止被篡改。严格来说,MD5不是一种加密算法而是摘要算法。无论是多...
  • 摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。 Python的hashlib提供了常见的摘要算法,如 MD5,SHA1,SHA512 等等。 提示: 要注意...
  • 散列算法进行数据验证与加密 散列算法 散列是信息的提炼,通常其长度要比信息小得多,且为一个固定长度。加密性强的散列一定是不可逆的,这就意味着通过散列结果,无法推出任何部分的原始信息。任何输入信息的...
  • 摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度数据转换为一个长度固定数据串(通常用16进制字符串表示)。 举个例子,你写了一篇文章,内容是一个字符串'how to use python hashlib - by M...
  • 摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度数据转换为一个长度固定数据串(通常用16进制字符串表示)。举个例子,你写了一篇文章,内容是一个字符串'how to use python hashlib - by Michael'...
  • shiro最闪亮的四大特征:认证,权限,加密,会话管理 ... 1.加密工具类的熟悉 ...2.通过shiro进行散列算法操作,常见的有两个MD5,SHA-1 简单的散列操作:代码如下 <span style="font-size:18px;">pu...
  • 包含 SHA-1,SHA-256,SHA-512,MD-5,CRC-32,Tiger-192 六种常见散列算法的库。xxx_f 包含计算函数,具有断点续算功能,类名不包括 _f 仅包含内存操作及比较函数。 用法:反复调用 void append(uint8_t *src, uint64...
  • 在实际的操作过程中,我们通常采用的方式是:采用非对称加密算法管理对称算法的密钥...常见的加密算法可以分成三类,对称加密算法,非对称加密算法和Hash算法。 https://www.cnblogs.com/colife/p/5566789.html AE...
  • Java哈希散列算法简介 - MD5 & SHA-512 在日常的开发工作中,我们常常会碰到这样的一个场景:我们需要有一种可靠的行之有效的方法来检验跟判断数据在传输过程当中的完整性。最常见的一种情况就是当我们传输文件...
  • 单向散列函数算法Hash算法 一种将任意长度的消息压缩到某一固定长度消息摘要的函数过程不可逆常见的单向散列算法有MD5,SHA.RIPE-MD,HAVAL,N-Hash 由于Hash函数的为不可逆算法所以软件智能使用Hash函数作为一个加密的...
  • 常见散列函数

    2020-11-02 16:44:49
    SHA(Secure Hash Algorithm)这是一种较新的散列算法,可以对任意长度的数据运算生成一个160位的数值。 MAC(Message Authentication Code):消息认证代码,是一种使用密钥的单向函数,可以用它们在系统上或...
  • 散列函数One-way Hash Functions - 一篇密码学纲要文章对单向散列函数简介。Cryptographic Hash Functions - SSH通讯安全公司密码... - RSA密码学常见问题解答中对散列函数类型简介。MD系列算法What are MD2,
  • 问题 我们通常需要对一些长文本字段建立唯一索引,比如,我们自己的应用里面,经常会有 URL 或者 URI 字段,里面保存类似:...这样的数据,并且要求唯一、不重复,常见的做法是创建一个唯一索引: create unique i
  • - 数据通过某一关键字或要素建立一个和存储地址相对应的映射关系,而建立这一映射过程则通过一个或多个特定的散列函数计算得到 - 特性 - 散列表用的是数组支持按照下标随机访问数据的特性,是对数组的一种扩展 - 再...
  • 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),比如加密密码“admin”,产生的散列值是“21232f297...
  • 哈希(Hash)也称为散列,就是把任意长度输入,通过散列算法,变换成固定长度输出,这个输出值就是散列值。 哈希算法 哈希表 哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问数据...
  • 散列

    2018-04-24 14:10:00
    1、定义 ... 散列常用作一种数据安全方法,由一串数据中经过散列算法计算出来资料指纹(data fingerprint),经常用来识别资料是否有被窜改,以保证资料确实是由原创者所提供。 散列算法的另一...
  • 常见的hash算法及其原理

    万次阅读 多人点赞 2018-07-30 15:47:13
    Hash,一般翻译做“散列”,也有直接音译为“哈希”,就是把任意长度输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值空间...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 870
精华内容 348
关键字:

常见的散列算法