• 对Redis布隆过滤器的实现


    目录

     实现思路

    首先最重要的自定义hash()

    然后就是将key放入bitSet

    然后就是判断布隆过滤器bitSet数组中是否含有对应的key

    代码


     

     实现思路

    (39条消息) Redis布隆过滤器_Fairy要carry的博客-CSDN博客

    首先最重要的自定义hash()

    1.首先判断key是否为null,否则返回0——>2.然后数组长度-1-i(目的使散列均匀,因为我们定义一个数组,全是辅助多次hash,所以需要-i保留特点),然后就是(size-1-i)&((h=key.hashcode())^h>>>16)——>3.非常关键在这里,计算key的hash值后,然后^key的hash>>>16,目的是保留key的特点,保证散列均匀,因为size-1-i(像hashMap默认size为16,那么15对应的二进制为1111,那么就只能与hash的低位四个进行运算,那么保留特点就很少),所以>>>16保留了key hash低位16的特点,然后再^key.hashCode()->保证了高位16的特点(这样就保证了key的特点)

    1. private int hash(Object key, int i) {
    2. int h;
    3. //BloomFilter_Size-i归根结底是为了保证散列均匀,保证每一次hash后key的特点——>之前push也是对key进行多次hash
    4. int index = key == null ? 0 : (BloomFilter_Size - 1 - i) & ((h = key.hashCode()) ^ (h >>> 16));
    5. return index > 0 ? index : -index;
    6. }

    然后就是将key放入bitSet

    思路:1.计算key的hash(利用辅助hash数组对key进行多次hash),得到位置index后放入数组

    1. /**
    2. * 2.存放key
    3. * 思路:1.遍历布隆过滤器的hash数组,对key进行多次hash并且保存在BitSet数组中
    4. *
    5. * @param key
    6. */
    7. public void push(Object key) {
    8. Arrays.stream(HelperBloom).forEach(i -> bitSet.set(hash(key, i)));
    9. currentBaseBean++;
    10. }

    然后就是判断布隆过滤器bitSet数组中是否含有对应的key

    思路:1.一样的,这里巧妙的是利用了&&,因为我们对key进行了多次hash,所以我们遍历辅助hash数组进行多次hash,根据对应index位置从bitSet取出看是否能取出,若为false,那么后面全为false——>2.直接利用&&,result默认为true,&&有一个为false那么结果就是false

    1. /**
    2. * 3.计算key的hash值并且去bitSet寻找看是否有位置,如果有返回true
    3. * 思路:利用&&,从bitSet取出对应key的hash的index,如果没有返回false,因为&&所以结果false
    4. *
    5. * @param key
    6. * @return
    7. */
    8. public boolean isContain(Object key) {
    9. boolean result=true;
    10. for (int i : HelperBloom) {
    11. result = result && bitSet.get(hash(key, i));
    12. }
    13. return result;
    14. }

    代码

    1. import java.util.Arrays;
    2. import java.util.BitSet;
    3. /**
    4. * @author diao 2022/9/7
    5. */
    6. public class BloomFilter {
    7. //后面hash函数会用到,用来生成不同的hash值,可以随便给,但别给奇数
    8. private final int[] ints = {6, 8, 16, 38, 58, 68};
    9. private Integer currentBeanCount = 0;
    10. //你的布隆过滤器容量
    11. private int DEFAULT_SIZE = Integer.MAX_VALUE;
    12. //bit数组,用来存放结果
    13. private final BitSet bitSet = new BitSet(DEFAULT_SIZE);
    14. public BloomFilter() {
    15. }
    16. public BloomFilter(int size) {
    17. if (size <= (2 << 8)) {
    18. throw new RuntimeException("size is too small");
    19. }
    20. DEFAULT_SIZE = size;
    21. }
    22. //获取当前过滤器的对象数量
    23. public Integer getCurrentBeanCount() {
    24. return currentBeanCount;
    25. }
    26. //计算出key的hash值,并将对应下标置为true
    27. public void push(Object key) {
    28. for (int i : ints) {
    29. bitSet.set(hash(key, i));
    30. }
    31. currentBeanCount++;
    32. }
    33. //判断key是否存在,true不一定说明key存在,但是false一定说明不存在
    34. public boolean contain(Object key) {
    35. boolean result = true;
    36. for (int i : ints) {
    37. result = result && bitSet.get(hash(key, i));
    38. }
    39. return result;
    40. }
    41. //hash算法,借鉴了hashmap的算法
    42. private int hash(Object key, int i) {
    43. int h;
    44. int index = key == null ? 0 : (DEFAULT_SIZE - 1 - i) & ((h = key.hashCode()) ^ (h >>> 16));
    45. return index > 0 ? index : -index;
    46. }
    47. public static void main(String[] args) {
    48. BloomFilter bf = new BloomFilter ();
    49. bf.push("张学友");
    50. bf.push("郭德纲");
    51. bf.push("特雷杨");
    52. bf.push(666);
    53. System.out.println(bf.contain("张学友"));//true
    54. System.out.println(bf.contain("张学友 "));//false
    55. System.out.println(bf.contain("张学友1"));//false
    56. System.out.println(bf.contain("郭德纲"));//true
    57. System.out.println(bf.contain("老鹰特雷杨8"));//false
    58. System.out.println(bf.contain(666));//true
    59. System.out.println(bf.contain(888));//false
    60. }
    61. }

     

  • 相关阅读:
    redhat 新开启一个ssh端口
    【iMessage苹果相册推位置推】“MFI授权计划”是指一个零丁的苹果程序开发
    【C++】抽象类 与 C++
    Azure 机器学习 - 机器学习中的企业安全和治理
    Flink中Table API和SQL(一)
    QGIS地理信息系统教程:GIS分析基础
    发布、部署,傻傻分不清楚?从概念到实际场景,再到工具应用,一篇文章让你彻底搞清楚
    人工智能对我们的生活影响有多大?
    Python实现print输出至日志文件
    git学习笔记 - 上传文件
  • 原文地址:https://blog.csdn.net/weixin_57128596/article/details/126739447