布隆过滤器的java实现代码, 自己实现的布隆过滤器和使用示例, Google的Guava包里面也有BloomFilter的实现。
MyBloomFilter.java
package cn.tekin.tools;
import java.util.Arrays;
import java.util.BitSet;
/**
* 布隆过滤器 JAVA实现代码
* @author Tekin <tekintian@gmail.com>
* @QQ 932256355
*/
public class MyBloomFilter {
// 二进制向量(数组)的位数,
// 2算术左移29 结果为 1073741824 10亿7千万bit
public static final int BIT_CAP = 2 << 29;
// 初始化BitSet容器
private final BitSet bits = new BitSet(BIT_CAP);
// 初始化Hash对象
private final Hash h = new Hash(BIT_CAP, 37);
public MyBloomFilter() {
}
/**
* 将要判断的数据(字符串)添加到过滤器中
*
* @param val
*/
public void addValue(String val) {
if (val != null) {
// 将字符串val 转换为整数 并作为set集合的key存入set集合,值为true
bits.set(h.hash(val), true);
}
}
/**
* 判断字符串是否包含在布隆过滤器中
*
* @param val
* @return
*/
public boolean contains(String val) {
if (val == null || val.isEmpty()) return false;
// 将要比较的字符串重新以上述方法计算hash值, 再根据这个值为key从bitset里面获取对应的值
int bitKey = h.hash(val);
return bits.get(bitKey);
}
/**
* 静态内部类
*/
private static class Hash {
// 二进制向量数组大小
private final int size;
// 随机数种子
private final int seed;
/**
* 构造函数
*
* @param cap
* @param seed
*/
public Hash(int cap, int seed) {
this.size = cap;
this.seed = seed;
}
/**
* 计算hash值
* 与运算 & 规则 :都为1时才为1
*
* @param val
* @return
*/
public int hash(String val) {
int result = 0;
int len = val.length();
// Hash算法 加权求和
for (int i = 0; i < len; i++) {
result += seed * result + val.charAt(i);
}
// 取模, 得到具体二进制数组下标
return (size - 1) & result;
}
/**
* 字符串hashCode计算 使用java内置的hashcode计算方法
* <p>
* 与运算 & 规则 :都为1时才为1
*
* @param val
* @return
*/
public int hcode(String val) {
// 这里进行与操作 确保返回数值为正数
return (size - 1) & Arrays.hashCode(val.getBytes());
}
}
}
布隆过滤器测试代码
package cn.tekin;
import cn.tekin.tools.MyBloomFilter;
import java.util.HashMap;
import java.util.UUID;
public class Main {
public static void main(String[] args) {
System.out.printf("Hello and welcome!");
MyBloomFilter mybf = new MyBloomFilter();
mybf.addValue("www.tekin.cn");
// 测试数据总数
int totalNum=1000000;
HashMap<Integer, String> testmap=new HashMap<Integer, String>(totalNum);
for (int i = 0; i < totalNum; i++) {
String val = UUID.randomUUID().toString();
testmap.put(i, val);
mybf.addValue(val);
}
mybf.addValue("www.baidu.com");
mybf.addValue("www.qq.com");
System.out.printf("\nwww.qq.com 查找结果:%b \n",mybf.contains("www.qq.com"));
int errCnt=0;
for (int i = 0; i < totalNum; i++) {
if (!mybf.contains(testmap.get(i))) {
System.out.printf("误报了,索引为:%d 值为:%s ", i, testmap.get(i));
errCnt++;
}
}
System.out.printf("\n总处理数据数:%d 条 误报数:%d %n",totalNum, errCnt);
}
}
布隆过滤器主要用于数据的存在/不存在判断, 如判断redis中是否有指定的key , 防止redis缓存击穿, 用于垃圾邮件过滤等。