Google Guava Hash(散列)

? ? ? ?Guava Hash(散列)指的是通過某種算法把數(shù)據(jù)源通過一系列的轉(zhuǎn)換生成一串字符串儡湾。常見的例如hash code生成眼溶,加密字符的生成授药,檢驗(yàn)字符的生成等等具滴。接下來我們就對Guava Hash(散列)的使用做一個(gè)介紹凹嘲。使用很簡單。Guava Hash(散列)里面也給我們提供了很多hash算法构韵。已經(jīng)能滿足我們大部分需求了周蹭。

一 Hash(散列)介紹

? ? ? ?Hash里面比較重要的類有:Hashing、HashFunction疲恢、Hasher凶朗、HashCode、Funnel显拳、PrimitiveSink棚愤。

1.1 Hashing

? ? ? ?Hashing類是一個(gè)幫助類,里面提供的方法都是根據(jù)不同的hash算法生成對應(yīng)的HashFunction對象杂数。每個(gè)hash算法都實(shí)現(xiàn)了HashFunction宛畦。Hashing類里面提供的方法如下。

  • [ goodFastHash(int minimumBits) ]: 返回一個(gè)多用途的揍移,臨時(shí)使用的次和,非加密的 Hash Function
  • [ murmur3_32(int seed) ]: 使用指定參數(shù)值做種子返回一個(gè) murmur3 算法實(shí)現(xiàn)的 32 位的哈希值
  • [ murmur3_32() ]: 使用零值種子返回一個(gè) murmur3 算法實(shí)現(xiàn)的 32 位的哈希值
  • [ murmur3_128() ]: 使用零值種子返回一個(gè) murmur3 算法實(shí)現(xiàn)的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 校驗(yàn)算法
  • [ crc32() ]:CRC-32 校驗(yàn)算法
  • [ adler32() ]:Adler-32 校驗(yàn)算法
  • [ farmHashFingerprint64() ]
  • [ consistentHash(HashCode hashCode, int buckets) ]:以給定 buckets 的大小分配一致性哈希罕邀,最大限度的減少隨 buckets 增長而進(jìn)行重新映射的需要读规。
  • [ consistentHash(long input, int buckets) ]
  • [ combineOrdered(Iterable<HashCode> hashCodes) ]:以有序的方式使 HashCode 結(jié)合起來,如果兩個(gè) HashCode 集合采用此種方法結(jié)合后的 HashCode 相同燃少,那么這兩個(gè) HashCode 集合中的元素可能是順序相等的束亏。
  • [ combineUnordered(Iterable<HashCode> hashCodes) ]: 以無序的方式使 HashCode 結(jié)合起來,如果兩個(gè) HashCode 集合采用此方法結(jié)合后的 HashCode 相同阵具,那么這兩個(gè) HashCode 集合中的元素可能在某種排序方式下是順序相等的碍遍。
  • [ concatenating(HashFunction first, HashFunction second, HashFunction... rest) ]: 將多個(gè)hash值拼接在一起定铜。比如你想要1024位的一個(gè)hash,你就可以Hashing.concatenating(Hashing.sha512(), Hashing.sha512())

1.2 HashFunction

? ? ? ?HashFunction有兩個(gè)作用:創(chuàng)建Hasher對象怕敬、也可以直接根據(jù)輸入條件返回HashCode結(jié)果揣炕。HashFunction里面常用函數(shù)如下:

public interface HashFunction {


    /**
     * 獲取一個(gè)Hasher
     */
    Hasher newHasher();
    Hasher newHasher(int expectedInputSize);

    /**
     * 根據(jù)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);

    /**
     * 根據(jù)一個(gè)對象生成HashCode
     */
    <T> HashCode hashObject(T instance, Funnel<? super T> funnel);

    /**
     * 返回此哈希生成的每個(gè)哈希代碼的位數(shù)(32的倍數(shù))
     */
    int bits();

}

1.3 Hasher

? ? ? ?Hasher的主要作用是根據(jù)加入的數(shù)據(jù)源得到HashCode。數(shù)據(jù)源通過提供的putXxx()方法添加东跪、hash()方法返回計(jì)算結(jié)果HashCode畸陡。

public interface Hasher extends PrimitiveSink {

    /**
     * 添加產(chǎn)生HashCode的數(shù)據(jù)源
     */
    @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);

    /** 
     * 添加一個(gè)對象數(shù)據(jù)源
     */
    <T> Hasher putObject(T instance, Funnel<? super T> funnel);

    /**
     * 獲取到HashCode
     */
    HashCode hash();

}

1.4 HashCode

? ? ? ?HashCode是對結(jié)果的一個(gè)封裝。

public abstract class HashCode {
    
    /**
     * 返回此HashCode中的位數(shù); 8的正數(shù)倍虽填,注意哦是bit
     */
    public abstract int bits();

    /**
     * 把HashCode的前面四個(gè)字節(jié)轉(zhuǎn)換為int(小端順序排列)
     *
     * @throws IllegalStateException if {@code bits() < 32}
     */
    public abstract int asInt();

    /**
     * 把HashCode的前面八個(gè)字節(jié)轉(zhuǎn)換為long(小端順序排列)
     *
     * @throws IllegalStateException if {@code bits() < 64}
     */
    public abstract long asLong();

    /**
     * 如果HashCode位數(shù)足夠多按照asLong()函數(shù)處理丁恭,不夠直接轉(zhuǎn)換為long
     */
    public abstract long padToLong();

    /**
     * HashCode以byte[]形式返回,字節(jié)數(shù)組的形式輸出
     */
    // 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轉(zhuǎn)換為32位長度的HashCode
     */
    public static HashCode fromInt(int hash);

    /**
     * 把long轉(zhuǎn)換為64位長度的HashCode
     */
    public static HashCode fromLong(long hash);

    /**
     * 把byte數(shù)組轉(zhuǎn)換為HashCode
     */
    public static HashCode fromBytes(byte[] bytes);
    
    /**
     * String轉(zhuǎn)換為HashCode
     */
    public static HashCode fromString(String string);
    
    /**
     * 返回hash code對應(yīng)的字符串
     */
    @Override
    public final String toString();

}

五 Funnel斋日、PrimitiveSink

? ? ? ?定義了怎樣將一個(gè)Object對象里面的各個(gè)屬性放到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 {

    /**
     * 把參數(shù)放到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);
    
}

? ? ? ?使用實(shí)例

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(散列)使用實(shí)例

2.1 各種算法對應(yīng)的hash code

        // 各種算法對應(yīng)的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 多個(gè)數(shù)據(jù)源對應(yīng)的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 數(shù)據(jù)源是對象的情況

    @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找到我們對應(yīng)需要的hash算法(一般里面的這些hash算法能滿足我們絕大部分的情況)第献。然后把數(shù)據(jù)源put進(jìn)去,如果有多個(gè)數(shù)據(jù)源依次put進(jìn)去就可以了兔港。最后hash()就得到了我們最終hash的結(jié)果了庸毫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市衫樊,隨后出現(xiàn)的幾起案子岔绸,更是在濱河造成了極大的恐慌,老刑警劉巖橡伞,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異晋被,居然都是意外死亡兑徘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門羡洛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挂脑,“玉大人,你說我怎么就攤上這事欲侮≌赶校” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵威蕉,是天一觀的道長刁俭。 經(jīng)常有香客問我,道長韧涨,這世上最難降的妖魔是什么牍戚? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任侮繁,我火速辦了婚禮,結(jié)果婚禮上如孝,老公的妹妹穿的比我還像新娘宪哩。我一直安慰自己,他們只是感情好第晰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布锁孟。 她就那樣靜靜地躺著,像睡著了一般茁瘦。 火紅的嫁衣襯著肌膚如雪品抽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天腹躁,我揣著相機(jī)與錄音桑包,去河邊找鬼。 笑死纺非,一個(gè)胖子當(dāng)著我的面吹牛哑了,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播烧颖,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼弱左,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了炕淮?” 一聲冷哼從身側(cè)響起拆火,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涂圆,沒想到半個(gè)月后们镜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡润歉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年模狭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片踩衩。...
    茶點(diǎn)故事閱讀 39,991評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嚼鹉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出驱富,到底是詐尸還是另有隱情锚赤,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布褐鸥,位于F島的核電站线脚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酒贬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一又憨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锭吨,春花似錦蠢莺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至考蕾,卻和暖如春祸憋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背肖卧。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工蚯窥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人塞帐。 一個(gè)月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓拦赠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親葵姥。 傳聞我的和親對象是個(gè)殘疾皇子荷鼠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 本文源地址:http://www.fullstackyang.com/... 一、背景知識 在網(wǎng)上已經(jīng)有很多關(guān)于布...
    flyer_cao閱讀 3,285評論 1 2
  • 散列表,它是基于高速存取的角度設(shè)計(jì)的榔幸,也是一種典型的“空間換時(shí)間”的做法允乐。顧名思義,該數(shù)據(jù)結(jié)構(gòu)能夠理解為一個(gè)線性表...
    江江JJ閱讀 1,906評論 0 6
  • 散列表,它是基于快速存取的角度設(shè)計(jì)的削咆,也是一種典型的“空間換時(shí)間”的做法牍疏。顧名思義,該數(shù)據(jù)結(jié)構(gòu)可以理解為一個(gè)線性表...
    yeying12321閱讀 3,691評論 0 6
  • 加密與解密 對稱密碼體制的保密性主要取決于密鑰的保密性拨齐,與算法的保密性無關(guān) 非對稱加密算法與對稱加密算法的區(qū)別: ...
    peerless_1024閱讀 1,925評論 0 0
  • 作為大家隨傳隨到的樹洞编矾,生了么陪許多寶媽聊過天熟史。近日一位寶媽跟生了么傾訴了她的煩惱,關(guān)于她的大女兒窄俏,關(guān)于家庭教育蹂匹。...
    生了么閱讀 801評論 0 0