BloomFilter过滤器代码原理介绍

BloomFilter过滤器代码原理介绍

通过多个hash函数的使用可以减少hash冲突的出现。

package com.xdclass.mobile.xdclassmobileredis.controller;
import java.util.BitSet;
//传统的Bloom filter 不支持从集合中删除成员。
//Counting Bloom filter由于采用了计数,因此支持remove操作。
//基于BitSet来实现,性能上可能存在问题
public class SimpleBloomFilter {
    //DEFAULT_SIZE为2的25次方
    private static final int DEFAULT_SIZE = 2 << 24;
    /* 不同哈希函数的种子,一般应取质数,seeds数据共有7个值,则代表采用7种不同的HASH算法 */
    private static final int[] seeds = new int[] { 5, 7, 11, 13, 31, 37, 61 };
    //BitSet实际是由“二进制位”构成的一个Vector。假如希望高效率地保存大量“开-关”信息,就应使用BitSet.
    //BitSet的最小长度是一个长整数(Long)的长度:64位
    private BitSet bits = new BitSet(DEFAULT_SIZE);
    /* 哈希函数对象 */
    private SimpleHash[] func = new SimpleHash[seeds.length];

    public static void main(String[] args) {
        String value = "stone2083@yahoo.cn";
        //定义一个filter,定义的时候会调用构造函数,即初始化七个hash函数对象所需要的信息。
        SimpleBloomFilter filter = new SimpleBloomFilter();
        //判断是否包含在里面。因为没有调用add方法,所以肯定是返回false
        System.out.println(filter.contains(value));
        filter.add(value);
        System.out.println(filter.contains(value));
    }
    //构造函数
    public SimpleBloomFilter() {
        for (int i = 0; i < seeds.length; i++) {
            //给出所有的hash值,共计seeds.length个hash值。共7位。
            //通过调用SimpleHash.hash(),可以得到根据7种hash函数计算得出的hash值。
            //传入DEFAULT_SIZE(最终字符串的长度),seeds[i](一个指定的质数)即可得到需要的那个hash值的位置。
            func[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]);
        }
    }

    // 将字符串标记到bits中,即设置字符串的7个hash值函数为1
    public void add(String value) {
        for (SimpleHash f : func) {
            bits.set(f.hash(value), true);
        }
    }

    //判断字符串是否已经被bits标记
    public boolean contains(String value) {
        //确保传入的不是空值
        if (value == null) {
            return false;
        }
        boolean ret = true;
        //计算7种hash算法下各自对应的hash值,并判断
        for (SimpleHash f : func) {
            //&&是boolen运算符,只要有一个为0,则为0。即需要所有的位都为1,才代表包含在里面。
            //f.hash(value)返回hash对应的位数值
            //bits.get函数返回bitset中对应position的值。即返回hash值是否为0或1。
            ret = ret && bits.get(f.hash(value));
        }
        return ret;
    }
    /* 哈希函数类 */
    public static class SimpleHash {
        //cap为DEFAULT_SIZE的值,即用于结果的最大的字符串长度。
        //seed为计算hash值的一个给定key,具体对应上面定义的seeds数组
        private int cap;
        private int seed;

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

        //计算hash值的具体算法,hash函数,采用简单的加权和hash
        public int hash(String value) {
            //int的范围最大是2的31次方减1,或超过值则用负数来表示
            int result = 0;
            int len = value.length();
            for (int i = 0; i < len; i++) {
                //数字和字符串相加,字符串转换成为ASCII码
                result = seed * result + value.charAt(i);
                //System.out.println(result+"--"+seed+"*"+result+"+"+value.charAt(i));
            }
            //  System.out.println("result="+result+";"+((cap - 1) & result));
            //  System.out.println(414356308*61+'h');  执行此运算结果为负数,为什么?
            //&是java中的位逻辑运算,用于过滤负数(负数与进算转换成反码进行)。
            return (cap - 1) & result;
        }
    }
}
上一篇:[数据算法]D1.BloomFilter


下一篇:Spark布隆过滤器(bloomFilter)