美文网首页
Google Guava Hash(散列)

Google Guava Hash(散列)

作者: tuacy | 来源:发表于2019-08-22 19:26 被阅读0次

           Guava Hash(散列)指的是通过某种算法把数据源通过一系列的转换生成一串字符串。常见的例如hash code生成,加密字符的生成,检验字符的生成等等。接下来我们就对Guava Hash(散列)的使用做一个介绍。使用很简单。Guava Hash(散列)里面也给我们提供了很多hash算法。已经能满足我们大部分需求了。

    一 Hash(散列)介绍

           Hash里面比较重要的类有:Hashing、HashFunction、Hasher、HashCode、Funnel、PrimitiveSink。

    1.1 Hashing

           Hashing类是一个帮助类,里面提供的方法都是根据不同的hash算法生成对应的HashFunction对象。每个hash算法都实现了HashFunction。Hashing类里面提供的方法如下。

    • [ goodFastHash(int minimumBits) ]: 返回一个多用途的,临时使用的,非加密的 Hash Function
    • [ murmur3_32(int seed) ]: 使用指定参数值做种子返回一个 murmur3 算法实现的 32 位的哈希值
    • [ murmur3_32() ]: 使用零值种子返回一个 murmur3 算法实现的 32 位的哈希值
    • [ murmur3_128() ]: 使用零值种子返回一个 murmur3 算法实现的128位的哈希值。
    • [ sipHash24() ]: sipHash24 加密算法
    • [ sipHash24(long k0, long k1) ]: sipHash24 加密算法
    • [ md5() ]: md5 加密算法。
    • [ sha1() ]:sha1算法,hash。
    • [ sha256() ]: sha256 加密算法
    • [ sha384() ]: sha384 加密算法
    • [ sha512() ]: sha512 加密算法
    • [ hmacMd5(Key key) ]: hmacMd5 加密算法
    • [ hmacMd5(byte[] key) ]:hmacMd5 加密算法
    • [ hmacSha1(Key key) ]:hmacSha1 加密算法
    • [ hmacSha1(byte[] key) ]:hmacSha1 加密算法
    • [ hmacSha256(Key key) ]:hmacSha256 加密算法
    • [ hmacSha256(byte[] key) ]:hmacSha256 加密算法
    • [ hmacSha512(Key key) ]:hmacSha512 加密算法
    • [ hmacSha512(byte[] key) ]:hmacSha512 加密算法
    • [ crc32c() ]:CRC32C 校验算法
    • [ crc32() ]:CRC-32 校验算法
    • [ adler32() ]:Adler-32 校验算法
    • [ farmHashFingerprint64() ]
    • [ consistentHash(HashCode hashCode, int buckets) ]:以给定 buckets 的大小分配一致性哈希,最大限度的减少随 buckets 增长而进行重新映射的需要。
    • [ consistentHash(long input, int buckets) ]
    • [ combineOrdered(Iterable<HashCode> hashCodes) ]:以有序的方式使 HashCode 结合起来,如果两个 HashCode 集合采用此种方法结合后的 HashCode 相同,那么这两个 HashCode 集合中的元素可能是顺序相等的。
    • [ combineUnordered(Iterable<HashCode> hashCodes) ]: 以无序的方式使 HashCode 结合起来,如果两个 HashCode 集合采用此方法结合后的 HashCode 相同,那么这两个 HashCode 集合中的元素可能在某种排序方式下是顺序相等的。
    • [ concatenating(HashFunction first, HashFunction second, HashFunction... rest) ]: 将多个hash值拼接在一起。比如你想要1024位的一个hash,你就可以Hashing.concatenating(Hashing.sha512(), Hashing.sha512())

    1.2 HashFunction

           HashFunction有两个作用:创建Hasher对象、也可以直接根据输入条件返回HashCode结果。HashFunction里面常用函数如下:

    public interface HashFunction {
    
    
        /**
         * 获取一个Hasher
         */
        Hasher newHasher();
        Hasher newHasher(int expectedInputSize);
    
        /**
         * 根据input生成HashCode
         */
        HashCode hashInt(int input);
        HashCode hashLong(long input);
        HashCode hashBytes(byte[] input);
        HashCode hashBytes(byte[] input, int off, int len);
        HashCode hashBytes(ByteBuffer input);
        HashCode hashUnencodedChars(CharSequence input);
        HashCode hashString(CharSequence input, Charset charset);
    
        /**
         * 根据一个对象生成HashCode
         */
        <T> HashCode hashObject(T instance, Funnel<? super T> funnel);
    
        /**
         * 返回此哈希生成的每个哈希代码的位数(32的倍数)
         */
        int bits();
    
    }
    

    1.3 Hasher

           Hasher的主要作用是根据加入的数据源得到HashCode。数据源通过提供的putXxx()方法添加、hash()方法返回计算结果HashCode。

    public interface Hasher extends PrimitiveSink {
    
        /**
         * 添加产生HashCode的数据源
         */
        @Override
        Hasher putByte(byte b);
        @Override
        Hasher putBytes(byte[] bytes);
        @Override
        Hasher putBytes(byte[] bytes, int off, int len);
        @Override
        Hasher putBytes(ByteBuffer bytes);
        @Override
        Hasher putShort(short s);
        @Override
        Hasher putInt(int i);
        @Override
        Hasher putLong(long l);
        @Override
        Hasher putFloat(float f);
        @Override
        Hasher putDouble(double d);
        @Override
        Hasher putBoolean(boolean b);
        @Override
        Hasher putChar(char c);
        @Override
        Hasher putUnencodedChars(CharSequence charSequence);
        @Override
        Hasher putString(CharSequence charSequence, Charset charset);
    
        /** 
         * 添加一个对象数据源
         */
        <T> Hasher putObject(T instance, Funnel<? super T> funnel);
    
        /**
         * 获取到HashCode
         */
        HashCode hash();
    
    }
    

    1.4 HashCode

           HashCode是对结果的一个封装。

    public abstract class HashCode {
        
        /**
         * 返回此HashCode中的位数; 8的正数倍,注意哦是bit
         */
        public abstract int bits();
    
        /**
         * 把HashCode的前面四个字节转换为int(小端顺序排列)
         *
         * @throws IllegalStateException if {@code bits() < 32}
         */
        public abstract int asInt();
    
        /**
         * 把HashCode的前面八个字节转换为long(小端顺序排列)
         *
         * @throws IllegalStateException if {@code bits() < 64}
         */
        public abstract long asLong();
    
        /**
         * 如果HashCode位数足够多按照asLong()函数处理,不够直接转换为long
         */
        public abstract long padToLong();
    
        /**
         * HashCode以byte[]形式返回,字节数组的形式输出
         */
        // TODO(user): consider ByteString here, when that is available
        public abstract byte[] asBytes();
    
        /**
         * HashCode放到dest里面去,并且返回放入的返回长度
         */
        @CanIgnoreReturnValue
        public int writeBytesTo(byte[] dest, int offset, int maxLength);
    
        /**
         * 把int转换为32位长度的HashCode
         */
        public static HashCode fromInt(int hash);
    
        /**
         * 把long转换为64位长度的HashCode
         */
        public static HashCode fromLong(long hash);
    
        /**
         * 把byte数组转换为HashCode
         */
        public static HashCode fromBytes(byte[] bytes);
        
        /**
         * String转换为HashCode
         */
        public static HashCode fromString(String string);
        
        /**
         * 返回hash code对应的字符串
         */
        @Override
        public final String toString();
    
    }
    
    

    五 Funnel、PrimitiveSink

           定义了怎样将一个Object对象里面的各个属性放到PrimitiveSink里面,Hasher的putObject方法需要传入这样的对象。

    Funnel

    public interface Funnel<T> extends Serializable {
    
      /**
       * Sends a stream of data from the {@code from} object into the sink {@code into}. There is no
       * requirement that this data be complete enough to fully reconstitute the object later.
       *
       * @since 12.0 (in Guava 11.0, {@code PrimitiveSink} was named {@code Sink})
       */
      void funnel(T from, PrimitiveSink into);
    }
    

    PrimitiveSink

    public interface PrimitiveSink {
    
        /**
         * 把参数放到PrimitiveSink里面去
         */
        PrimitiveSink putByte(byte b);
        PrimitiveSink putBytes(byte[] bytes);
        PrimitiveSink putBytes(byte[] bytes, int off, int len);
        PrimitiveSink putBytes(ByteBuffer bytes);
        PrimitiveSink putShort(short s);
        PrimitiveSink putInt(int i);
        PrimitiveSink putLong(long l);
        PrimitiveSink putFloat(float f);
        PrimitiveSink putDouble(double d);
        PrimitiveSink putBoolean(boolean b);
        PrimitiveSink putChar(char c);
        PrimitiveSink putUnencodedChars(CharSequence charSequence);
        PrimitiveSink putString(CharSequence charSequence, Charset charset);
        
    }
    

           使用实例

    Funnel<Person> personFunnel = new Funnel<Person>() {
        @Override
        public void funnel(Person person, PrimitiveSink into) {
            into
                .putInt(person.id)
                .putString(person.firstName, Charsets.UTF_8)
                .putString(person.lastName, Charsets.UTF_8)
                .putInt(birthYear);
        }
    }
    

    二 Hash(散列)使用实例

    2.1 各种算法对应的hash code

            // 各种算法对应的hash code
            String input = "hello, world";
            // MD5
            System.out.println(Hashing.md5().hashBytes(input.getBytes()).toString());
            // sha256
            System.out.println(Hashing.sha256().hashBytes(input.getBytes()).toString());
            // sha512
            System.out.println(Hashing.sha512().hashBytes(input.getBytes()).toString());
            // crc32
            System.out.println(Hashing.crc32().hashBytes(input.getBytes()).toString());
            // MD5
            System.out.println(Hashing.md5().hashUnencodedChars(input).toString());
    

    2.2 多个数据源对应的hash code

            HashFunction hf = Hashing.md5();
            HashCode hc = hf.newHasher()
                    .putLong(10)
                    .putString("abc", Charsets.UTF_8)
                    .hash();
            System.out.println(hc.toString());
    

    2.3 数据源是对象的情况

        @Test
        public void objectToHashCode() {
    
            // 需要hash的对象
            Person person = new Person(27, "wu", "xing", 1990);
    
            Funnel<Person> personFunnel = new Funnel<Person>() {
                @Override
                public void funnel(Person person, PrimitiveSink into) {
                    into
                            .putInt(person.id)
                            .putString(person.firstName, Charsets.UTF_8)
                            .putString(person.lastName, Charsets.UTF_8)
                            .putInt(person.birthYear);
                }
            };
    
            // md5算法
            HashFunction hf = Hashing.md5();
            HashCode hc = hf.newHasher()
                    .putString("abc", Charsets.UTF_8)
                    .putObject(person, personFunnel)
                    .hash();
            System.out.println(hc.toString());
        }
    
        class Person {
            int id;
            String firstName;
            String lastName;
            int birthYear;
    
            public Person(int id, String firstName, String lastName, int birthYear) {
                this.id = id;
                this.firstName = firstName;
                this.lastName = lastName;
                this.birthYear = birthYear;
            }
        }
    

           Guava Hash(散列)的使用很简单吧,首先在Hashing找到我们对应需要的hash算法(一般里面的这些hash算法能满足我们绝大部分的情况)。然后把数据源put进去,如果有多个数据源依次put进去就可以了。最后hash()就得到了我们最终hash的结果了。

    相关文章

      网友评论

          本文标题:Google Guava Hash(散列)

          本文链接:https://www.haomeiwen.com/subject/zqmosctx.html