深入浅出数据结构之布隆过滤器

简介: 深入浅出数据结构之布隆过滤器

当需要判断某个元素是否处于某个集合中时,为了快速查询可以使用散列表Map来进行存储元素

散列表本身就是空间换时间的数据结构,当元素数量多且元素所占空间非常大时,使用散列表会占用大量空间

比如爬虫要爬取很多网络地址,想要过滤掉已经访问过的地址时,可以使用布隆过滤器

布隆过滤器

什么是布隆过滤器呢?布隆过滤器并不是LOL中布隆拿着的大盾牌

布隆过滤器由位数组与多个哈希函数构成

image.png

当将某个元素加入集合时,使用多个哈希函数对该元素得到索引位置,将位数组该索引位置变为1

判断该元素是否加入集合时,也使用多个哈希函数对该元素得到索引位置,判断位数组中索引位置是否为1,都为1说明加入过集合,否则未加入

由于索引位置上的1可能是其他元素设置的,布隆过滤器存在一定误差, 误差率随着位数组长度的增大而减小

布隆过滤器的时间复杂度为O(n个哈希函数),空间复杂度为O(位数组长度)

实现

定义类

定义布隆过滤器类

使用long数组充当位数组,hashSize记录hash函数数量,泛型存储对应类型元素

public class BloomFilter<T> {
    /**
     * 位数组
     */
    private long[] bit;

    /**
     * 一共有多少个二进制位
     */
    private int bitSize;

    /**
     * hash函数数量
     */
    private int hashSize;
}

添加元素

put添加元素,先对元素进行检查,再循环使用多个哈希函数生成索引设置为1

  /**
     * 添加元素
     *
     * @param value
     * @return 发生变化返回true,未发生变化返回false
     */
    public boolean put(T value) {
        //空指针检查
        nullCheck(value);

        // 利用元素生成2个整数,将这2个整数经过hash函数生成的索引赋值为1
        int hash1 = value.hashCode();
        int hash2 = hash1 >>> 16;

        boolean result = false;
        for (int i = 1; i <= hashSize; i++) {
            //相当于hash函数 生成一个二进位的索引index
            int combinedHash = hash1 + (i * hash2);
            if (combinedHash < 0) {
                combinedHash = ~combinedHash;
            }
            int index = combinedHash % bitSize;
            
            // 设置index位置的二进位为1
            if (set(index)) {
                result = true;
            }
        }
        return result;
    }
  /**
     * 设置index位置的二进位为1
     *
     * @param index
     * @return
     */
    private boolean set(int index) {
        //找到对应的long值value  用value | (1<<k)
        
        //找到索引所在数组位置,一个long是64位
        long value = bit[index / Long.SIZE];
        //获得long值对应要修改为1的索引 (0-63)
        int k = index % Long.SIZE;
        
        bit[index / Long.SIZE] = value | (1 << k);
        //   101010101010010001
        // | 000000000000000100   1 << k
        //   101010111010010101

        //如果原来value与1<<k对应的位置是0则返回true,是1则返回false
        return (value & (1 << k))==0 ;
    }

判断元素是否存在

   /**
     * 判断元素value是否存在
     * @param value
     * @return false:一定不存在  true:可能存在
     */
    public boolean contains(T value) {
        nullCheck(value);
        //先按照Put前面的步骤找到value对应的索引位置
        int hash1 = value.hashCode();
        int hash2 = hash1 >>> 16;


        for (int i = 1; i <= hashSize; i++) {
            int combinedHash = hash1 + (i * hash2);
            if (combinedHash < 0) {
                combinedHash = ~combinedHash;
            }
            int index = combinedHash % bitSize;
            if (!get(index)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断index位置的二进制位数是否为1
     * @param index
     * @return
     */
    private boolean get(int index){
        long value = bit[index / Long.SIZE];
        int k = index % Long.SIZE;
        //如果value与1<<k对应的位置是1则返回true,是0则返回false
        return (value & (1 << k)) != 0;
    }

总结

布隆过滤器由位数组与多个哈希函数构成

布隆过滤器适用于判断多元素是否加入过集合,特点是占用空间小, 速度快,可能出现误差

本篇文章将被收入数据结构专栏,觉得不错感兴趣的同学可以收藏专栏哟~

觉得菜菜写的不错,可以点赞、关注支持哟~

有什么问题可以在评论区交流喔~


相关文章
|
6月前
|
存储 算法 NoSQL
海量数据处理数据结构之Hash与布隆过滤器
随着网络和大数据时代的到来,我们如何从海量的数据中找到我们需要的数据就成为计算机技术中不可获取的一门技术,特别是近年来抖音,快手等热门短视频的兴起,我们如何设计算法来从大量的视频中获取当前最热门的视频信息呢,这就是我们今天即将谈到的Hash和布隆过滤器。以下是Hash和布隆过滤器的一些常见应用:
64 2
|
6月前
|
存储 算法 搜索推荐
【数据结构】哈希经典应用:布隆过滤器(哈希+位图)——[深度解析](9)
【数据结构】哈希经典应用:布隆过滤器(哈希+位图)——[深度解析](9)
|
5月前
|
存储 机器学习/深度学习 缓存
【数据结构】布隆过滤器原理详解及其代码实现
【数据结构】布隆过滤器原理详解及其代码实现
|
6月前
|
算法 Go 数据库
数据结构/C++:位图 & 布隆过滤器
数据结构/C++:位图 & 布隆过滤器
43 0
|
6月前
|
存储 NoSQL 算法
深入浅出Redis(十一):Redis四种高级数据结构:Geosptial、Hypeloglog、Bitmap、Bloom Filter布隆过滤器
深入浅出Redis(十一):Redis四种高级数据结构:Geosptial、Hypeloglog、Bitmap、Bloom Filter布隆过滤器
|
6月前
|
存储 数据库 C++
高效处理大规模数据集的概率型数据结构—— 布隆过滤器 [C++入门]
高效处理大规模数据集的概率型数据结构—— 布隆过滤器 [C++入门]
89 0
|
6月前
|
算法
【数据结构】盘点那些经典的 [哈希面试题]【哈希切割】【位图应用】【布隆过滤器】(10)
【数据结构】盘点那些经典的 [哈希面试题]【哈希切割】【位图应用】【布隆过滤器】(10)
|
存储 NoSQL Redis
【Redis的那些事 · 续集】Redis的位图、HyperLogLog数据结构演示以及布隆过滤器
位图的最小单位是bit,每个bit的值只能是0和1,位图的应用场景一般用于一些签到记录,例如打卡等。场景举例: 例如某APP要存储用户的打卡记录,如果按照正常的思路来做,可能是用户每天是否打卡的记录都单独设置一个key-value键值对来存储,这样的话,每个用户每天都需要耗费一个键值对空间。而如果是位图,就可以很方便地通过位图来进行记录
194 0
【Redis的那些事 · 续集】Redis的位图、HyperLogLog数据结构演示以及布隆过滤器
|
存储 缓存 NoSQL
漫谈 LevelDB 数据结构(二):布隆过滤器(Bloom Filter)
漫谈 LevelDB 数据结构(二):布隆过滤器(Bloom Filter)
223 0
漫谈 LevelDB 数据结构(二):布隆过滤器(Bloom Filter)
|
存储 数据采集 缓存
数据结构与算法必知--- Bitmap位图与布隆过滤器
数据结构与算法必知--- Bitmap位图与布隆过滤器