其他分享
首页 > 其他分享> > 布隆过滤器

布隆过滤器

作者:互联网

布隆过滤器


原理

插入

布隆过滤器(BloomFilter) 将待插入的元素通过预先设置的M个哈希函数进行运算,得到M个K值,每个K值表示事先初始化的一个长度为 N的比特位数组上的第K个位置(k<=N),最后将这M位置设置为1

查询

将要查询的元素经过 M个哈希函数进行运算,得到对应于比特位数组上的 M 个位置,如果M 个位置有一个为 0,则元素肯定不存在,如果 M 个位置全部为 1,则可能存在。

实现

其中,关于M个函数的模拟可以采用如下这种技巧,用2个哈希函数来模拟k个哈希函数。即:

g(x) = h1(x) + ih2(x) ,其中0 <= i <= k-1

 @Resource
//    private StringRedisTemplate stringRedisTemplate;

    public void put(String target) {

        int[] offset = getHashOffSet(target);
        // redis bitmap 保存offset
//        stringRedisTemplate.executePipelined (new RedisCallback<Object>() {
//            public Object doInRedis(RedisConnection connection) throws DataAccessException {
//                StringRedisConnection stringRedisConn = (StringRedisConnection) connection;
//                for (int i : offset) {
//                    stringRedisConn.setBit(key, i, true);
//                }
//                return null;
//            }
//        }
    }

    private int[] getHashOffSet(String target) {
        int numHashFunctions = 32, bitSize = 32;
        int[] offset = new int[numHashFunctions];
        long hash64 = Hashing.murmur3_128().hashString(target, UTF_8).asLong();
        int hash1 = (int) hash64;
        int hash2 = (int) (hash64 >>> 32);

        for (int i = 1; i <= numHashFunctions; i++) {
            int nextHash = hash1 + i * hash2;
            if (nextHash < 0) {
                nextHash = ~nextHash;
            }
            offset[i - 1] = nextHash % bitSize;
        }
        return offset;
    }

得到的offset比特位数组我们可以借助redis的bitmap位图数据结构进行保存。

 public boolean isExit(String target) {
        boolean result = true;
        List<Boolean> resultList = stringRedisTemplate.execute(new RedisCallback<List<Boolean>>() {
            @Override
            public List<Boolean> doInRedis(RedisConnection connection) throws DataAccessException {
                List<Boolean> resultList = Lists.newArrayList();
                StringRedisConnection stringRedisConn = (StringRedisConnection) connection;
                for (int i : offset) {
                    resultList.add(stringRedisConn.getBit(target, i));
                }
                return resultList;
            }
        });

        for (Boolean isTrue : resultList) {
            if (!isTrue) {
                result = false;
                break;
            }
        }
        
        return result;
    }

判断是否存在对应元素时也是通过getHashOffSet得到待查询元素的的比特位数组,然后遍历该数组,数组的值假设为k,则查询redis上该key的第k个位置是否为1,1则返会true,0返回false。

应用

缺点及改进

标签:target,int,布隆,查询,resultList,哈希,offset,过滤器
来源: https://blog.csdn.net/legendaryhaha/article/details/112535150