布隆过滤器(BloomFilter)——简介(一)

布隆过滤器(BloomFilter)——简介(一)

1970年布隆提出了BloomFilter,它被用作对数据进行初级的过滤,降低过滤数据的成本。BloomFilter就像粗糙的大筛子一样,使用它过滤细沙,先将所有的沙石倒进大筛子,能够初步将太大的沙石过滤掉,但是不能保证所有留下的就是我们想要的细沙(因为粗糙的筛子的孔大小不一,同时制作成本较低,即使制作一个能够过滤大量沙石的大筛子,也能接受)。接着再用一个精细的小筛子来对剩下的沙石进行过滤,就能够过滤出所有符合大小限制的细沙。(精细化的筛子制作成本高,但是因为足够小,所以其成本是能够接受的)。这就是一个关于布隆过滤器的产生的描述。

1. 基本概念

  • 描述
    BloomFilter是一种概率型数据结构,利用概率学进行设计的数据结构 。我们先可以直接理解为它是一个"集合"(当然这不是真的^_^,后面会再写一篇说明它是如何设计的) ,可以高效地插入和查询数据。它主要的功能是用来判断BloomFilter这个"集合"中是否存在某个元素,不过它只能告诉你“这个元素在BloomFilter中一定不存在或者可能存在”,也就是说BloomFilter可能会错误的认为某个不存在其中的元素存在其中,但是BloomFilter认为不存在的元素那就一定不存在其中
    BloomFilter不存在存在
    实际不存在不存在存在
  • 特点
    • 基于概率学的数据结构
    • 用来判断集合中是否存在某个元素,但是有一定的误判率(非常低,可自定),常用作超大数据的初级过滤
    • 插入和查询的效率都是常量级别(查询只能看元素是否存在)
    • 无法删除元素
    • 内存占用低(内存占用比HashSet少很多,占用大小的计算可参考bloom-calculator

2. BloomFilter和HashSet的性能比较

  • 依次修改数据量大小,记录不同容量的查询效率(每次查询1000000次)

    判断器10万100万500万1000万2000万3000万5000万1亿2亿5亿
    BloomFilter285ms288ms186ms182ms197ms198ms188ms189ms191ms173ms
    HashSet22ms30ms21ms17ms23ms-----
  • 依次修改插入的数据量,记录每次的插入时间

    判断器10万100万500万1000万2000万3000万5000万1亿2亿5亿
    BloomFilter96ms518ms2807ms5888ms13147ms20713ms35675ms73075ms152333ms380256ms
    HashSet21ms121ms2971ms6632ms22494ms内存溢出内存溢出内存溢出内存溢出内存溢出

    注: 在我的PC上测试时,此处BloomFilter的容错率设定为1%

  • 分析
    可以看出:查询方面,随着容器数据量的增大,HashSet的查询效率几乎不变,BloomFilter的查询效率会逐步提高趋于稳定;插入方面,随着插入数据量的增加,刚开始HashSet比BloomFilter快,到后面被BloomFilter超越,直接被远远甩在后面,甚至因为占用内存空间太大的问题,导致内存溢出。

3. BloomFilter使用示例

  • 导包 pom.xml
<!-- 这里选择的是谷歌guava提供的BloomFilter,使用maven导入依赖 -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>28.0-jre</version>
</dependency>
  • 使用示例
import com.google.common.base.Charsets;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnel;
import com.google.common.hash.PrimitiveSink;

/**
 * Description: 布隆过滤器示例
 *
 * @author ALion
 * @version 2019/8/17 1:52
 */
public class BloomFilterDemo {

    public static void main(String[] args) {
        // Funnel用于告诉BloomFilter需要根据Person的哪些字段来计算其信息指纹
        Funnel<Person> personFunnel = new Funnel<Person>() {
            @Override
            public void funnel(Person person, PrimitiveSink into) {
                into.putInt(person.id)
                    .putString(person.firstName, Charsets.UTF_8);
            }
        };

        int count = 100 * 10000;
        
        // arg1: Funnel
        // arg2: 指定你的BloomFilter要容纳多少条数据
        // arg3: 指定创建的BloomFilter的错误率
        BloomFilter<Person> friends = BloomFilter.create(personFunnel, count, 0.01);

        // 向BloomFilter中加入数据
        for (int i = 0; i < count; i++) {
            friends.put(new Person(i, "jack" + i));
        }

        // 测试效果
        Person person1 = new Person(10, "jack");
        boolean exist1 = friends.mightContain(person1);
        System.out.println("person1: exist = " + exist1);

        Person person2 = new Person(10, "jack10");
        boolean exist2 = friends.mightContain(person2);
        System.out.println("person2: exist = " + exist2);

    }

    static class Person {

        int id;

        String firstName;

        public Person(int id, String firstName) {
            this.id = id;
            this.firstName = firstName;
        }

    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值