生活随笔
收集整理的這篇文章主要介紹了
[Google Guava] 10-散列
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文鏈接?譯文鏈接?譯者:沈義揚
概述
Java內建的散列碼[hash code]概念被限制為32位,并且沒有分離散列算法和它們所作用的數據,因此很難用備選算法進行替換。此外,使用Java內建方法實現的散列碼通常是劣質的,部分是因為它們最終都依賴于JDK類中已有的劣質散列碼。
Object.hashCode往往很快,但是在預防碰撞上卻很弱,也沒有對分散性的預期。這使得它們很適合在散列表中運用,因為額外碰撞只會帶來輕微的性能損失,同時差勁的分散性也可以容易地通過再散列來糾正(Java中所有合理的散列表都用了再散列方法)。然而,在簡單散列表以外的散列運用中,Object.hashCode幾乎總是達不到要求——因此,有了com.google.common.hash包。
散列包的組成
在這個包的Java doc中,我們可以看到很多不同的類,但是文檔中沒有明顯地表明它們是怎樣 一起配合工作的。在介紹散列包中的類之前,讓我們先來看下面這段代碼范例:
| 1 | HashFunction hf = Hashing.md5(); |
| 2 | HashCode hc = hf.newHasher() |
| 4 | ????????.putString(name, Charsets.UTF_8) |
| 5 | ????????.putObject(person, personFunnel) |
HashFunction
HashFunction是一個單純的(引用透明的)、無狀態的方法,它把任意的數據塊映射到固定數目的位指,并且保證相同的輸入一定產生相同的輸出,不同的輸入盡可能產生不同的輸出。
Hasher
HashFunction的實例可以提供有狀態的Hasher,Hasher提供了流暢的語法把數據添加到散列運算,然后獲取散列值。Hasher可以接受所有原生類型、字節數組、字節數組的片段、字符序列、特定字符集的字符序列等等,或者任何給定了Funnel實現的對象。
Hasher實現了PrimitiveSink接口,這個接口為接受原生類型流的對象定義了fluent風格的API
Funnel
Funnel描述了如何把一個具體的對象類型分解為原生字段值,從而寫入PrimitiveSink。比如,如果我們有這樣一個類:
| 3 | ????final?String firstName; |
| 4 | ????final?String lastName; |
| 5 | ????final?int?birthYear; |
它對應的Funnel實現可能是:
| 01 | Funnel<Person> personFunnel =?new?Funnel<Person>() { |
| 03 | ????public?void?funnel(Person person, PrimitiveSink into) { |
| 05 | ????????????.putInt(person.id) |
| 06 | ????????????.putString(person.firstName, Charsets.UTF_8) |
| 07 | ????????????.putString(person.lastName, Charsets.UTF_8) |
| 08 | ????????????.putInt(birthYear); |
注:putString(“abc”, Charsets.UTF_8).putString(“def”, Charsets.UTF_8)完全等同于putString(“ab”, Charsets.UTF_8).putString(“cdef”, Charsets.UTF_8),因為它們提供了相同的字節序列。這可能帶來預料之外的散列沖突。增加某種形式的分隔符有助于消除散列沖突。
HashCode
一旦Hasher被賦予了所有輸入,就可以通過hash()方法獲取HashCode實例(多次調用hash()方法的結果是不確定的)。HashCode可以通過asInt()、asLong()、asBytes()方法來做相等性檢測,此外,writeBytesTo(array, offset, maxLength)把散列值的前maxLength字節寫入字節數組。
布魯姆過濾器[BloomFilter]
布魯姆過濾器是哈希運算的一項優雅運用,它可以簡單地基于Object.hashCode()實現。簡而言之,布魯姆過濾器是一種概率數據結構,它允許你檢測某個對象是一定不在過濾器中,還是可能已經添加到過濾器了。布魯姆過濾器的維基頁面對此作了全面的介紹,同時我們推薦github中的一個教程。
Guava散列包有一個內建的布魯姆過濾器實現,你只要提供Funnel就可以使用它。你可以使用create(Funnel funnel, int expectedInsertions, double falsePositiveProbability)方法獲取BloomFilter<T>,缺省誤檢率[falsePositiveProbability]為3%。BloomFilter<T>提供了boolean mightContain(T)?和void put(T),它們的含義都不言自明了。
| 01 | BloomFilter<Person> friends = BloomFilter.create(personFunnel,?500,?0.01); |
| 02 | for(Person friend : friendsList) { |
| 03 | ????friends.put(friend); |
| 07 | if?(friends.mightContain(dude)) { |
| 08 | ????//dude不是朋友還運行到這里的概率為1% |
| 09 | ????//在這兒,我們可以在做進一步精確檢查的同時觸發一些異步加載 |
Hashing類
Hashing類提供了若干散列函數,以及運算HashCode對象的工具方法。
已提供的散列函數
| md5() | murmur3_128() | murmur3_32() | sha1() |
| sha256() | sha512() | goodFastHash(int bits) | ? |
HashCode運算
| 方法 | 描述 |
| HashCode?combineOrdered( Iterable<HashCode>) | 以有序方式聯接散列碼,如果兩個散列集合用該方法聯接出的散列碼相同,那么散列集合的元素可能是順序相等的 |
| HashCode ? combineUnordered( Iterable<HashCode>) | 以無序方式聯接散列碼,如果兩個散列集合用該方法聯接出的散列碼相同,那么散列集合的元素可能在某種排序下是相等的 |
| int ? consistentHash( HashCode, int buckets) | 為給定的”桶”大小返回一致性哈希值。當”桶”增長時,該方法保證最小程度的一致性哈希值變化。詳見一致性哈希。 |
原創文章,轉載請注明:?轉載自并發編程網 – ifeve.com本文鏈接地址:?[Google Guava] 10-散列
from:?http://ifeve.com/google-guava-hashing/?
總結
以上是生活随笔為你收集整理的[Google Guava] 10-散列的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。