赞
踩
最近在学习Redis缓存穿透等知识的时候看到了布隆过滤器可以用于解决缓存穿透问题,因此对布隆过滤器进行了学习,并记录下此篇笔记。
根据百度百科可知,布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。
布隆过滤器主要由一个位标记数组和一系列随机映射函数(hash)组成,hash函数负责计算hash值,然后标记对应的标记位,因此就需要一个位标记数组了。
布隆过滤器主要有几个过程:
布隆过滤器在添加元素的时候,会进行如下操作:
流程图大概为如下:
布隆过滤器在判断元素是否存在的时候,会进行如下操作:
流程图大概如下:
所以在判断元素是否存在的时候,我们可以直接拿hash对应的位数进行&
操作,就可以得出是否存在了。
从上面的原理我们可以看出,如果布隆过滤器判断该元素存在,则该元素不一定存在,因为有可能是另一个字符串hash冲突导致的位数状态为true
;但是如果布隆过滤器判断该元素不存在,则该元素一定不存在。
从上面我们可以得知,如果要实现一个布隆过滤器的话,需要实现以下:
代码如下:
import java.util.BitSet; /** * @ClassName MyBloomFilter * @Description 自己实现的布隆过滤器 * @Author cxc * @Date 2020/10/6 15:57 * @Verseion 1.0 **/ public class MyBloomFilter { /** * 标记位数组的大小 **/ private static final int DEFAULT_SIZE = 2 << 24; /** * 根据这个数组来创建多个hash函数 **/ private static final int[] SEEDS = new int[]{3, 13, 46, 71, 91, 134}; /** * 标记位数组 **/ private BitSet bitSet = new BitSet(DEFAULT_SIZE); /** * hash函数数组 **/ private SimpleHash [] simpleHashes = new SimpleHash[SEEDS.length]; /** * @Description: 构造器 * @Author: caixucheng * @Date: 2020/10/6 16:22 * @version: v1.0.0 **/ public MyBloomFilter(){ // 初始化hash数组 for (int i = 0;i < SEEDS.length;++i){ simpleHashes[i] = new SimpleHash(SEEDS.length,SEEDS[i]); } } /** * @Description: 将一个元素添加到布隆过滤器中 * @Author: caixucheng * @Date: 2020/10/6 16:05 * @param value: 元素 * @version: v1.0.0 **/ public void add(Object value){ // 分别计算value的hash值然后将对应的位置true for (SimpleHash s : simpleHashes){ bitSet.set(s.hash(value),true); } } /** * @Description: 判断一个元素是否在布隆过滤器中 * @Author: caixucheng * @Date: 2020/10/6 16:27 * @param value: 元素 * @return: boolean 存在则返回true,否则返回false * @version: v1.0.0 **/ public boolean isContain(Object value){ boolean res = true; // 计算全部的hash值,看看是否全为true for (SimpleHash s : simpleHashes){ res &= bitSet.get(s.hash(value)); } return res; } /** * @Description: 静态内部类,用于实现hash * @Author: caixucheng * @Date: 2020/10/6 15:58 * @version: v1.0.0 **/ public static class SimpleHash{ private int cap; private int seed; public SimpleHash(int cap,int seed){ this.cap = cap; this.seed = seed; } /** * @Description: hash函数 * @Author: caixucheng * @Date: 2020/10/6 16:00 * @param value: 需要进行hash的值 * @return: int 返回hash计算出来的值 * @version: v1.0.0 **/ public int hash(Object value){ int h; return (value == null) ? 0 : Math.abs(seed * (cap - 1) & ((h = value.hashCode()) ^ (h >>> 16))); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。