手写布隆过滤器

是什么:

        判断某个数据是否在大数据量集合中,并且不占内存

        它可以告诉你某种东西一定不存在或者可能存在

能干什么:

        1 之前爬过100万个url ,判断url是否爬取过?

        2 有10亿个电话,判断某个号码是否在这10亿个中?

        4解决缓存穿透 把已经存在的key放到布隆过滤器里,如果用布隆过滤器查询没有就直接返回没有,如果有就是可能有,就算通过,能大大减少数据库并发

原理:

        有2个主要方法,放入和查询。

        1 放入过滤器数据,数据会进行多次hash 然后hash节点对应的结果 标注为1,如果已经是1就还是1

        2 查询:使用查询的值进行多次hash,如果对应的hash位置都是1 那就有可能有,如果有一个不是1就一定没有(有可能有是因为数据量大,hash的多导致坑都被占)

其他点:

        1 布隆过滤器不能删除已经放进去的节点,因为有可能已经叠加了,会破坏过滤器功能

        2 布隆过滤器不能扩容,因为他节省空间的优势,所以没有元数据,hash数据结果不可逆,所以不能扩容,这里如果扩容方案就是,新建一个更大的布隆过滤器,新的数据添加到新的过滤器上,两个过滤器一起用。

java代码:

package 算法;

import java.util.ArrayList;
import java.util.List;

public class 布隆过滤器 {

    //布隆过滤器(Bloom Filter)详解
    public static class BloomFilter {
        int[] bloomArr;
        int limit;
        //hash次数
        int hashSize = 4;
        List<String> list;

        /**
         * 初始化布隆大小
         *
         * @param size
         */
        public BloomFilter(int size) {
            limit = size;
            this.bloomArr = new int[size];
            list = new ArrayList<>();
            list.add("asdf");
            list.add("hgjk");
            list.add("dsaf");
            list.add("grgrg");
        }

        /**
         * 放入数据
         *
         * @param value
         */
        public void put(String value) {
            for (int i = 0; i < hashSize; i++) {
                int j = getHash(value + list.get(i));
                bloomArr[j] = 1;
            }
        }

        /**
         * 判断数据是否在
         * ture 不一定存在
         * false 一定不存在
         *
         * @param value
         */
        public boolean exist(String value) {
            for (int i = 0; i < hashSize; i++) {
                int j = getHash(value + i);
                if (bloomArr[j] == 0) {
                    return false;
                }
            }
            return true;
        }

        private int getHash(String value) {
            return toAbs(value.hashCode() % limit);
        }

        //取绝对值方法
        //int类型存入是以二进制补码的形式在内存中,要取绝对值,只需要改变其符号位
        public int toAbs(int n) {
            int i = n >> 31;             //int 为32位,右移31位得到符号位,赋值给i,若为正,则i==0;负,i==-1
            return ((n ^ i) - i);        //一个数^0==原数,数^-1==数的绝对值-1   ==》 绝对值=负数异或-1取反+1
        }
    }

    public static void main(String[] args) {

        //创建
        BloomFilter bloomFilter = new BloomFilter(100);

        bloomFilter.put("chenchen");
        bloomFilter.put("超人");
        bloomFilter.put("蜘蛛侠");
        bloomFilter.put("钢铁侠");
        bloomFilter.put("咸蛋超人");
        //判断验证
        List<String> list = new ArrayList<>();
        list.add("chenchen");
        list.add("咸蛋超人");
        list.add("123");
        list.add("555");
        for (String s : list) {
            if (bloomFilter.exist(s)) {
                System.out.println(s + ":有可能有");
            } else {
                System.out.println(s + ":一定没有");
            }
        }


    }
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值