zoukankan      html  css  js  c++  java
  • java8 hash算法

    一、hash算法

      哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明文而且哪怕只更改该段落的一个字母,随后的哈希都将产生不同的值。要找到散列为同一个值的两个不同的输入,在计算上是不可能的,所以数据的哈希值可以检验数据的完整性。一般用于快速查找和加密算法。

    二、对象hash总结

    Integer、Byte、Short、Character都是转换为int类型作为hashcode

    Boolean true值hashcode为1231,false值hashcode为1237

    Long  取高32位和低32位与值转成int类型作为hashcode

    Double  将64bit值转成long类型,然后按照Long类型进行获取hashcode

    Float  将32bit值转成int类型,检查int值是否来自NAN值转换的,若是hashcode为0x7fc00000,否则为该转换值。

    String 将字符串里面的字符以31进制求和,既hash=hash*31+value[i]

    Object 以内存首字节的地址进行计算hash值

    HashMap 将所有Entry的hashcode相加组成HashMap的hashcode

    Hashtable EntrySet长度0或者加载因子小于0时,hashcode为0,否则将所有key的hashcode相加组成HashMap的hashcode

    三、jdk的hash算法实现

    (1)Interger

        private final int value;
    
        @Override
        public int hashCode() {
            return Integer.hashCode(value);
        }
    
        public static int hashCode(int value) {
            return value;
        }

    Integer的hash算法就是直接获取它的数值。int整数范围很大,分散广冲突小。

    (2)Short

        private final short value;
    
        @Override
        public int hashCode() {
            return Short.hashCode(value);
        }
    
        public static int hashCode(short value) {
            return (int)value;
        }

    (3)Byte

        private final byte value;
    
        @Override
        public int hashCode() {
            return Byte.hashCode(value);
        }
    
        public static int hashCode(byte value) {
            return (int)value;
        }

    (4)Long

        private final long value;
    
        @Override
        public int hashCode() {
            return Long.hashCode(value);
        }
        
        public static int hashCode(long value) {
            return (int)(value ^ (value >>> 32));
        }

    long类型作为索引范围太大,需要转为int类型。这里简单的获取低32位容易导致散列不均,因为高位部分没有被利用。所以这里采用逻辑右移32位,让高32位和低32位进行XOR操作,导致高位低位都能被利用到

    (5)Double

        private final double value;
    
        @Override
        public int hashCode() {
            return Double.hashCode(value);
        }
    
        public static int hashCode(double value) {
            long bits = doubleToLongBits(value);
            return (int)(bits ^ (bits >>> 32));
        }

    由于double不能当成索引,所以需要转换成整数

    由于double数据类型底层采用64位bit码表示,采用IEEE浮点标准编码。如果将它使用8字节整数编码方式,就能获取一个long类型的数字

    long类型作为索引范围太大,需要转为int类型。这里简单的获取低32位容易导致散列不均,因为高位部分没有被利用。所以这里采用逻辑右移32位,让高32位和低32位进行XOR操作,导致高位低位都能被利用到

    最后得到的数字强转int,只保留已经被充分打乱的低32位

    (6)Float

         private final float value;
    
        @Override
        public int hashCode() {
            return Float.hashCode(value);
        }
    
        public static int hashCode(float value) {
            return floatToIntBits(value);
        }
    
        public static int floatToIntBits(float value) {
            int result = floatToRawIntBits(value);
            // Check for NaN based on values of bit fields, maximum
            // exponent and nonzero significand.
            if ( ((result & FloatConsts.EXP_BIT_MASK) ==
                  FloatConsts.EXP_BIT_MASK) &&
                 (result & FloatConsts.SIGNIF_BIT_MASK) != 0)
                result = 0x7fc00000;
            return result;
        }
    
        public static native int floatToRawIntBits(float value);
    public class FloatConsts {
        public static final int EXP_BIT_MASK = 2139095040;
        public static final int SIGNIF_BIT_MASK = 8388607;
        //...
    }

    (7)Boolean

        private final boolean value;
    
        @Override
        public int hashCode() {
            return Boolean.hashCode(value);
        }
    
        public static int hashCode(boolean value) {
            return value ? 1231 : 1237;
        }

    采用两个质数作为true或false的索引。这两个质数足够大,用来作为索引时,出现碰撞的可能性低。

    (8)Character

        private final char value;
    
        @Override
        public int hashCode() {
            return Character.hashCode(value);
        }
    
        public static int hashCode(char value) {
            return (int)value;
        }

    (9)String

        private final char value[];
    
        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作为基数,逐位加权,打乱整个字符的权重和排列位置,使得散列效果更好。

    (10)Object

        public native int hashCode();

    (11)自定义对象

    public class Node<T> {
    
        private T data;
        private Node<T> next = null;
        
        @Override
        public int hashCode() {
            int hash = 3;
            hash = 97 * hash + Objects.hashCode(this.data);
            hash = 97 * hash + Objects.hashCode(this.next);
            return hash;
        }
    }
    public final class Objects {
        public static int hashCode(Object o) {
            return o != null ? o.hashCode() : 0;
        }
        //...
    }

    (12)HashMap

        static final int hash(Object key) {
            int h;
            return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
        }
    
        public int hashCode() {
            int h = 0;
            Iterator<Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext())
                h += i.next().hashCode();
            return h;
        }

    (13)Hashtable

       public synchronized V put(K key, V value) {
            // Make sure the value is not null
            if (value == null) {
                throw new NullPointerException();
            }
    
            // Makes sure the key is not already in the hashtable.
            Entry<?,?> tab[] = table;
            int hash = key.hashCode();
            int index = (hash & 0x7FFFFFFF) % tab.length;
            @SuppressWarnings("unchecked")
            Entry<K,V> entry = (Entry<K,V>)tab[index];
            for(; entry != null ; entry = entry.next) {
                if ((entry.hash == hash) && entry.key.equals(key)) {
                    V old = entry.value;
                    entry.value = value;
                    return old;
                }
            }
    
            addEntry(hash, key, value, index);
            return null;
        }
    
        public synchronized int hashCode() {
    
            int h = 0;
            if (count == 0 || loadFactor < 0)
                return h;  // Returns zero
    
            loadFactor = -loadFactor;  // Mark hashCode computation in progress
            Entry<?,?>[] tab = table;
            for (Entry<?,?> entry : tab) {
                while (entry != null) {
                    h += entry.hashCode();
                    entry = entry.next;
                }
            }
    
            loadFactor = -loadFactor;  // Mark hashCode computation complete
    
            return h;
        }
  • 相关阅读:
    java开发异常类型汇总
    dm642在线写EPROM.txt
    [Codecademy] HTML&CSS 第一课:HTML Basic
    bram和dram差别
    Advanced Fruits HDU杭电1503【LCS的保存】
    add Admob with Cocos2d-x on iOS
    一种基于Qt的可伸缩的全异步C/S架构server实现(五) 单层无中心集群
    【SSH2框架(理论篇)】--SSH2 Vs 经典三层
    CSS BFC学习笔记
    【智能家居篇】wifi网络结构(上)
  • 原文地址:https://www.cnblogs.com/maokun/p/7482279.html
Copyright © 2011-2022 走看看