本文章也同步至本人的CSDN博客中: http://blog.csdn.net/u012881584/article/details/70477832
今天來說一個Java中處理大文本字符串慮重的兩個解決方案。
相信大家在實際工作中都遇到過數(shù)據(jù)重復的問題, 當然也就存在慮重的工作。
比如數(shù)據(jù)庫中需要對同一個字段進行慮重, 大多數(shù)情況下我們直接使用Set就能解決問題, 今天我所說的這個大文本慮重是什么含義呢?一起來看看需求吧。
需求:
公司SEO人員給了我一個文本文件, 里面大概有三千多萬行字符串, 他們的要求是希望我用最短的時間把這個文本文件重復的給刪除掉。 起初我想的直接用excle去處理吧, 當時 因為這個文件都達到了幾百兆, 所以編輯修改起來都很費勁。
這里直接給出解決思路:
首先腦海中想到的第一個就是用大數(shù)據(jù)去處理, 只是耳邊經(jīng)常聽過Hadoop,Spark之類的詞, 但是自己也并未真正接觸過。于是便一通Google, 然后找到兩個解決方案。
利用布隆過濾器去解決。
利用Spark的distinct去解決。
1, 布隆過濾器
原理
如果想判斷一個元素是不是在一個集合里,一般想到的是將集合中所有元素保存起來,然后通過比較確定。鏈表、樹、散列表(又叫哈希表,Hash table)等等數(shù)據(jù)結構都是這種思路。但是隨著集合中元素的增加,我們需要的存儲空間越來越大。同時檢索速度也越來越慢。
Bloom Filter 是一種空間效率很高的隨機數(shù)據(jù)結構,Bloom filter 可以看做是對 bit-map 的擴展, 它的原理是:
當一個元素被加入集合時,通過 K 個 Hash 函數(shù)將這個元素映射成一個位陣列(Bit array)中的 K 個點,把它們置為 1。檢索時,我們只要看看這些點是不是都是 1 就(大約)知道集合中有沒有它了:
如果這些點有任何一個 0,則被檢索元素一定不在;
如果都是 1,則被檢索元素很可能在。
優(yōu)點
It tells us that the element either definitely is not in the set or may be in the set.
它的優(yōu)點是空間效率和查詢時間都遠遠超過一般的算法,布隆過濾器存儲空間和插入 / 查詢時間都是常數(shù)O(k)。另外, 散列函數(shù)相互之間沒有關系,方便由硬件并行實現(xiàn)。布隆過濾器不需要存儲元素本身,在某些對保密要求非常嚴格的場合有優(yōu)勢。缺點
但是布隆過濾器的缺點和優(yōu)點一樣明顯。誤算率是其中之一。隨著存入的元素數(shù)量增加,誤算率隨之增加。但是如果元素數(shù)量太少,則使用散列表足矣。
(誤判補救方法是:再建立一個小的白名單,存儲那些可能被誤判的信息。)
另外,一般情況下不能從布隆過濾器中刪除元素. 我們很容易想到把位數(shù)組變成整數(shù)數(shù)組,每插入一個元素相應的計數(shù)器加 1, 這樣刪除元素時將計數(shù)器減掉就可以了。然而要保證安全地刪除元素并非如此簡單。首先我們必須保證刪除的元素的確在布隆過濾器里面. 這一點單憑這個過濾器是無法保證的。另外計數(shù)器回繞也會造成問題。
這里只是簡單做個介紹, 有興趣的盆友可以參考:
網(wǎng)友評論