生成 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 的大小就能解决同样的问题。