算法学习--布隆过滤器

布隆过滤器

  • 布隆过滤器Bloom Filter,是1970年由布隆提出的;它实际上是一个很长的二进制向量(BitMap)一系列随机映射函数
  • 可以用于检索一个元素是否在一个集合中
  • 优点:空间效率查询时间都很好
  • 缺点:有一定的误识别率删除困难,通常是只增/查不删
  • 原理:当一个元素被加入集合时,通过k个散列函数将这个元素映射成一个位数组中的k个点,把他们设置为1;检索时,我们只要看这些点是不是都是1就可以大约知道集合中是否有这个值,只要存在一个点不为1,则被检测的元素一定不存在,若全为1,则认为元素很可能存在
  • 代码实现
//布隆过滤器
public class BloomFilter {
    private static final int NumSlots = 1024 * 1024 * 8; //位图的宽度
    private static final int NumHash = 8; //Hash函数的个数,一个Hash函数的结果标记一个位
    private BigInteger bitmap = new BigInteger("0"); //位图

    //处理原始数据,每一个Hash函数对应出一个位,Hash的值域为0~(NumSlots-1)
    public void addElement(String message){
        //有几个hash函数就执行几次
        for (int i = 0; i < NumHash; i++) {
            //获取此时hash函数得到的值
            int hashCode = getHash(message, i);
            //如果位图的该位为0,将该为置为1
            if(!bitmap.testBit(hashCode)){
                //shiftLeft表示将1左移hashCode位,再与原始bitmap或运算,即可将bitmap的该位置为1
                bitmap = bitmap.or(new BigInteger("1").shiftLeft(hashCode));
            }
        }
    }

    //Hash函数,n代表第几个hash函数
    private int getHash(String message, int n){
        message = message + n;
        try {
            //获取md5的实例,md5将任意输入映射成128位的整数
            MessageDigest md5 = MessageDigest.getInstance("md5");
            byte[] bytes = message.getBytes();
            //使用md5将bytes转化为128位的整数
            md5.update(bytes);
            BigInteger bi = new BigInteger(md5.digest());
            return Math.abs(bi.intValue())%NumSlots;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return -1;
    }

    //查询是否在集合中
    public boolean check(String message){
        for (int i = 0; i < NumHash; i++) {
            //如果位图中该位为0
            if(!this.bitmap.testBit(getHash(message, i))){
                //一定不存在
                return false;
            }
        }
        //每一位都存在,可能存在
        return true;
    }

    //测试
    public static void main(String[] args) {
        BloomFilter bloomFilter = new BloomFilter();
        Random random = new Random();
        bloomFilter.addElement("123456");
        for (int i = 0; i < 1000; i++) {
            bloomFilter.addElement(i*8*(i-1) + random.nextInt(1000) + "");
        }
        System.out.println(bloomFilter.check("123456")); //true
        System.out.println(bloomFilter.check("1236")); //false
        System.out.println(bloomFilter.check("13579242356547")); //false
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值