布隆过滤器

布隆过滤器是一种概率型数据结构,用于高效地插入和查询,能判断某元素可能不存在或可能存在。其核心是BitMap,通过多哈希函数将元素映射到数组并置1。误判源于相同位被多次映射,导致无法删除。在Java中实现布隆过滤器,需要位数组、多个哈希函数及插入、查询方法。
摘要由CSDN通过智能技术生成

布隆过滤器

概念

布隆过滤器本质上是一种比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”

数据结构

布隆过滤器由一个BitMap组成。所谓的BitMap,本质上就是一个数组。与寻常数组不同的是,BitMap一个数组元素占一个bit,这一特性决定了BitMap能够极大地节省空间

在这里插入图片描述

当使用布隆过滤器时,每添加一个元素都会进行以下操作:

  1. 对需要添加的元素进行n种hash计算
  2. 将hash计算的结果对应的BitMap位进行置1操作。

在这里插入图片描述

而对于查询操作来说(判断某元素是否存在),将会进行以下操作:

  1. 对需要查询的元素进行n种hash计算
  2. 查询hash计算的结果对应的BitMap位是否为1。若都为1,则代表该元素有可能存在;若存在非1位,则代表该元素一定不存在

误判

需要注意的是,布隆过滤器无法确定元素存在,只能确定元素不存在。出现的原因是多个输入经过哈希之后在相同的bit位置1了,这样就无法判断究竟是哪个输入产生的,因此误判的根源在于相同的 bit 位被多次映射且置 1。

这种情况也造成了布隆过滤器的删除问题,即布隆过滤器不存在删除操作。因为布隆过滤器的每一个 bit 并不是独占的,很有可能多个元素共享了某一位。如果我们直接删除这一位的话,会影响其他的元素。

Java实现布隆过滤器

想要手动实现一个的话,你需要:

  1. 一个合适大小的位数组保存数据
  2. 几个不同的哈希函数
  3. 添加元素到位数组(布隆过滤器)的方法实现
  4. 判断给定元素是否存在于位数组(布隆过滤器)的方法实现。
import java.util.BitSet;

public class MyBloomFilter {

    /**
     * 位数组的大小
     */
    private static final int DEFAULT_SIZE = 2 << 24;
    /**
     * 通过这个数组可以创建 6 个不同的哈希函数
     */
    private static final int[] SEEDS = new int[]{3, 13, 46, 71, 91, 134};

    /**
     * 位数组。数组中的元素只能是 0 或者 1
     */
    private BitSet bits = new BitSet(DEFAULT_SIZE);

    /**
     * 存放包含 hash 函数的类的数组
     */
    private SimpleHash[] func = new SimpleHash[SEEDS.length];

    /**
     * 初始化多个包含 hash 函数的类的数组,每个类中的 hash 函数都不一样
     */
    public MyBloomFilter() {
        // 初始化多个不同的 Hash 函数
        for (int i = 0; i < SEEDS.length; i++) {
            func[i] = new SimpleHash(DEFAULT_SIZE, SEEDS[i]);
        }
    }

    /**
     * 添加元素到位数组
     */
    public void add(Object value) {
        for (SimpleHash f : func) {
            bits.set(f.hash(value), true);
        }
    }

    /**
     * 判断指定元素是否存在于位数组
     */
    public boolean contains(Object value) {
        boolean ret = true;
        for (SimpleHash f : func) {
            ret = ret && bits.get(f.hash(value));
        }
        return ret;
    }

    /**
     * 静态内部类。用于 hash 操作!
     */
    public static class SimpleHash {

        private int cap;
        private int seed;

        public SimpleHash(int cap, int seed) {
            this.cap = cap;
            this.seed = seed;
        }

        /**
         * 计算 hash 值
         */
        public int hash(Object value) {
            int h;
            return (value == null) ? 0 : Math.abs(seed * (cap - 1) & ((h = value.hashCode()) ^ (h >>> 16)));
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值