项目实战Bloomfilter

176 阅读1分钟

开发场景: 制作主播排行榜单(白名单),大概10W + 的主播,但是白名单只有1W +,已经存在与表,拉取插入bloomfilter,项目初始化即可存入bloomfilter,每次制作榜单需要的数据即可过滤主播 手动实现BloomFilter代码:

/**
 * @description:  手动实现bloomFilter,可能存在,一定不存在
 * @author: Ding Yawu
 * @create: 2022/2/1 14:21
 */
public class MyBloomFilter {

    // 位数组的大小
    private static final int DEFAULT_SIZE = 2 << 24;

    // hash函数的种子
    private static final int[] SEEDS = new int[]{3, 13, 46};

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

    // hash函数
    private ExtHash[] func = new ExtHash[SEEDS.length];

    public MyBloomFilter() {
        for (int i = 0; i < SEEDS.length; i++) {
            func[i] = new ExtHash(DEFAULT_SIZE, SEEDS[i]);
        }
    }

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

        }
    }

    // 判断指定元素是否存在于位数组
    public boolean contains(Object value) {
        boolean ret = true;
        for (ExtHash f : func) {
            ret = ret && bits.get(f.hash(value));
            // hash函数有一个计算出为false,则直接返回
            if (!ret) {
                return ret;
            }
        }
        return ret;
    }

    // hash函数类
    public static class ExtHash {

        private int cap;
        private int seed;

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

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

    }

    public static void main(String[] args) {
        Integer value1 = 13423;
        Integer value2 = 22131;
        MyBloomFilter filter = new MyBloomFilter();
        // false
        System.out.println(filter.contains(value1));
        // false
        System.out.println(filter.contains(value2));
        filter.add(value1);
        filter.add(value2);
        // true
        System.out.println(filter.contains(value1));
        // true
        System.out.println(filter.contains(value2));
    }
}

我对BloomFilter的理解就是可能存在,但一定不存在尤其适合做榜单数据的时候要求不是那么精确,即使像邮件那样错判了也是可以接受的。

测试guava包的BloomFilter

/**
 * @description:
 * @author: Ding Yawu
 * @create: 2022/2/1 14:36
 */
public class GuavaFilter {
  public static void main(String[] args) {
      // 创建布隆过滤器对象,最多元素数量为50000,期望误报概率为0.01
      BloomFilter<Integer> filter = BloomFilter.create(Funnels.integerFunnel(), 50000, 0.01);
      // 判断指定元素是否存在
      // false
      System.out.println(filter.mightContain(1));
      // false
      System.out.println(filter.mightContain(2));
      // 将元素添加进布隆过滤器
      filter.put(1);
      filter.put(2);
      // true
      System.out.println(filter.mightContain(1));
      // true
      System.out.println(filter.mightContain(2));
  }
}

guava包中轮子已经造好了,拿来直接使用就好了,在实践中也可以直接采用redis的bloom插件。