1. 程式人生 > >[Google Guava] 10-雜湊

[Google Guava] 10-雜湊

原文連結 譯文連結 譯者:沈義揚

概述

Java內建的雜湊碼[hash code]概念被限制為32位,並且沒有分離雜湊演算法和它們所作用的資料,因此很難用備選演算法進行替換。此外,使用Java內建方法實現的雜湊碼通常是劣質的,部分是因為它們最終都依賴於JDK類中已有的劣質雜湊碼。

Object.hashCode往往很快,但是在預防碰撞上卻很弱,也沒有對分散性的預期。這使得它們很適合在散列表中運用,因為額外碰撞只會帶來輕微的效能損失,同時差勁的分散性也可以容易地通過再雜湊來糾正(Java中所有合理的散列表都用了再雜湊方法)。然而,在簡單散列表以外的雜湊運用中,Object.hashCode幾乎總是達不到要求——因此,有了

com.google.common.hash包。

雜湊包的組成

在這個包的Java doc中,我們可以看到很多不同的類,但是文件中沒有明顯地表明它們是怎樣 一起配合工作的。在介紹雜湊包中的類之前,讓我們先來看下面這段程式碼範例:

HashFunction hf = Hashing.md5();
HashCode hc = hf.newHasher()
        .putLong(id)
        .putString(name, Charsets.UTF_8)
        .putObject(person, personFunnel)
        .hash();

HashFunction

HashFunction是一個單純的(引用透明的)、無狀態的方法,它把任意的資料塊對映到固定數目的位指,並且保證相同的輸入一定產生相同的輸出,不同的輸入儘可能產生不同的輸出。

Hasher

HashFunction的例項可以提供有狀態的Hasher,Hasher提供了流暢的語法把資料新增到雜湊運算,然後獲取雜湊值。Hasher可以接受所有原生型別、位元組陣列、位元組陣列的片段、字元序列、特定字符集的字元序列等等,或者任何給定了Funnel實現的物件。

Hasher實現了PrimitiveSink介面,這個介面為接受原生型別流的物件定義了fluent風格的API

Funnel

Funnel描述瞭如何把一個具體的物件型別分解為原生欄位值,從而寫入PrimitiveSink。比如,如果我們有這樣一個類:

class Person {
    final int id;
    final String firstName;
    final String lastName;
    final int birthYear;
}

它對應的Funnel實現可能是:

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);
    }
}

注:putString(“abc”, Charsets.UTF_8).putString(“def”, Charsets.UTF_8)完全等同於putString(“ab”, Charsets.UTF_8).putString(“cdef”, Charsets.UTF_8),因為它們提供了相同的位元組序列。這可能帶來預料之外的雜湊衝突。增加某種形式的分隔符有助於消除雜湊衝突。

HashCode

布魯姆過濾器[BloomFilter]

布魯姆過濾器是雜湊運算的一項優雅運用,它可以簡單地基於Object.hashCode()實現。簡而言之,布魯姆過濾器是一種概率資料結構,它允許你檢測某個物件是一定不在過濾器中,還是可能已經新增到過濾器了。布魯姆過濾器的維基頁面對此作了全面的介紹,同時我們推薦github中的一個教程

BloomFilter<Person> friends = BloomFilter.create(personFunnel, 500, 0.01);
for(Person friend : friendsList) {
    friends.put(friend);
}

// 很久以後
if (friends.mightContain(dude)) {
    //dude不是朋友還執行到這裡的概率為1%
    //在這兒,我們可以在做進一步精確檢查的同時觸發一些非同步載入
}

Hashing類

Hashing類提供了若干雜湊函式,以及運算HashCode物件的工具方法。

已提供的雜湊函式

HashCode運算