生成 url 文件
#!/usr/bin/env bash
file='./bigFile.txt'
urlPre='https://blog.csdn.net/u010979642/'
[ $1 ] && count=$1 || count=10
for num in $(seq 1 ${count})
do
# 隨機生成 count 以內的隨機數
randomNum=$(($RANDOM%${count}))
echo ${urlPre}${randomNum} >> ${file}
done
引入maven依賴
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
使用 BloomFilter 對url集進行去重
public static void main(String[] args) {
long start = System.currentTimeMillis();
String sourceFile = "C:\\Users\\answer\\Desktop\\bigFile.txt";
// 初始化一個存儲String數據的布隆過濾器
// expectedInsertions: 預估的元素個數, fpp: 誤判率, 默認值0.03, 誤判率越低所要求的內存越大
BloomFilter<CharSequence> bloomFilter = BloomFilter.create(
Funnels.stringFunnel(Charset.forName("utf-8")), 1000000, 0.00001);
Set<String> urls = Sets.newHashSet();
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(sourceFile))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
if (!bloomFilter.mightContain(line)) {
bloomFilter.put(line);
urls.add(line);
} else {
System.out.println(String.format("line=[%s]已經存在", line));
}
}
long end = System.currentTimeMillis();
System.out.println(
String.format("共耗時[%d]秒, 去重後個數=[%d], urls=[%d]",
(end - start) / 1000,
bloomFilter.approximateElementCount(),
urls.size()
)
);
} catch (IOException e) {
e.printStackTrace();
}
}
loomFilter<User> bloomFilter = BloomFilter.create(
(from, into) -> into.putString(from.getUserName(), Charsets.UTF_8),
10000,
0.01);
Bloom Filter的應用
-
cerberus在收集監控數據的時候, 有的系統的監控項量會很大, 需要檢查一個監控項的名字是否已經被記錄到db過了, 如果沒有的話就需要寫入db.
-
爬蟲過濾已抓到的url就不再抓,可用bloom filter過濾
-
垃圾郵件過濾。如果用哈希表,每存儲一億個 email地址,就需要 1.6GB的內存(用哈希表實現的具體辦法是將每一個 email地址對應成一個八字節的信息指紋,然後將這些信息指紋存入哈希表,由於哈希表的存儲效率一般只有 50%,因此一個 email地址需要佔用十六個字節。一億個地址大約要 1.6GB,即十六億字節的內存)。因此存貯幾十億個郵件地址可能需要上百 GB的內存。而Bloom Filter只需要哈希表 1/8到 1/4 的大小就能解決同樣的問題。