• 布隆过滤器


     作用:磁盘上有很大的数据,查找数据,去重,查找次数,能用于计数吗??

    bitmap :一个数据是32位的,就有2的32次种可能,所有有2的32的bits;

    布隆:你数据虽然是32位的,但我的位的个数和你有多少数据n有关,和你的数据位数没有关系。。。

     常用的m=16n,k=8;

    在面试时遇到的问题,问题的解决方案十分典型,但对于海量数据处理接触少的同学可能一时也想不到什么好方案。介绍两个算法,对于空间的利用到达了一种极致,那就是Bitmap和布隆过滤器(Bloom Filter)

    Bitmap算法

    在网上并没有找到Bitmap算法的中文翻译,在《编程珠玑》中有提及。与其说是算法,不如说是一种紧凑的数据存储结构。其实如果并非如此大量的数据,有很多排重方案可以使用,典型的就是哈希表

    public int[] removeDuplicates(int[] array) {
        int index = 0;
        Map<Integer, Boolean> maps = new LinkedHashMap<Integer, Boolean>();
        for(int num : array) {
            if(!maps.contains(num)) {
                array[index] = num;
                index++;
                maps.put(num, true);
            }
        }
    
        return newArray;
    }
    

     

    实际上,哈希表实际上为每一个可能出现的数字提供了一个一一映射的关系,每个元素都相当于有了自己的独享的一份空间,这个映射由散列函数来提供(这里我们先不考虑碰撞)。实际上哈希表甚至还能记录每个元素出现的次数,这样的数据结构完成这个任务有点“大材小用”了。

    我们拆解一下我们的需求:

    1. 集合中每个元素(示例中是int)有一个独享的空间
    2. 找到一个到这个空间的映射方法

    这个空间要多大?对于我们的问题来说,一个boolean就够了,或者说,1个bit就够了,我们只想知道某个元素出现过没有。如果为每个所有可能的值分配1个bit,32bit的int所有可能取值需要内存空间为:

     
    232bit=229Byte=512MB232bit=229Byte=512MB

    那怎么样完成这个映射呢?其实就是Bitmap所要完成的工作了。如果我们把整型0x01、0x02、…、0x08的空间依次映射到一个Byte上,每个bit就代表这个int值是否出现过,初值为0(false)。

    其实,就是按int从小到大的顺序依次摆放到byte[]中,仅涉及到一些除以2的整次幂和对2的整次幂取余的位操作小技巧。很显然,对于小数据量、数据取值很稀疏,上面的方法并没有什么优势,但对于海量的、取值分布很均匀的集合进行去重,Bitmap极大地压缩了所需要的内存空间。于此同时,还额外地完成了对原始数组的排序工作。缺点是,Bitmap对于每个元素只能记录1bit信息,如果还想完成额外的功能,恐怕只能靠牺牲更多的空间、时间来完成了。

    布隆过滤器(Bloom Filter)

    然而Bitmap不是万能的,如果数据量大到一定程度,如开头写的64bit类型的数据,还能不能用Bitmap?我们来算一算:

     
    264bit=261Byte=2048PB=2EB264bit=261Byte=2048PB=2EB

    EB(Exabyte,艾字节)这个计算机科学中统计数据量的单位有多大,有兴趣的小伙伴可以查阅下资料。这个量级的Bitmap,已经不是人类硬件所能承担的了。我相信谁也不会想用集群去计算这么一个问题吧?所以Bitmap的好处在于空间复杂度不随原始集合内元素的个数增加而增加,而它的坏处也源于这一点——空间复杂度随集合内最大元素增大而线性增大

    所以接下来,我们要引入另一个著名的工业实现——布隆过滤器(Bloom Filter)。如果说Bitmap对于每一个可能的整型值,通过直接寻址的方式进行映射,相当于使用了一个哈希函数,那布隆过滤器就是引入了k(k>1)k(k>1)个相互独立的哈希函数,保证在给定的空间、误判率下,完成元素判重的过程。下图中是k=3k=3时的布隆过滤器。

    图1 布隆过滤器(来源:wiki)

     

  • 相关阅读:
    JS给数字加千位分隔符
    前端防抖与节流实现与应用
    JS实现单向链表、双向链表、循环链表
    单点登录
    AMD、CMD规范
    JS实现全排列
    event loop、进程和线程、任务队列
    BOM属性对象方法
    JS的闭包、高阶函数、柯里化
    for...in、for...of、forEach()有什么区别
  • 原文地址:https://www.cnblogs.com/mdumpling/p/8656885.html
Copyright © 2020-2023  润新知