布隆过滤器的实现及使用

  1. 创建一个BloomFilter类
import java.util.BitSet;
import java.util.Random;

public class BloomFilter {
    /**
     * 位数组,用于存储布隆过滤器的状态
     */
    private BitSet bitSet;
    /**
     * 位数组的长度
     */
    private int bitSetSize = 2 << 24;
    /**
     * 预期元素数量
     */
    private int expectedNumberOfElements = 2000000;
    /**
     * 哈希函数数量
     */
    private int numberOfHashFunctions;
    /**
     * 用于生成哈希种子的伪随机数生成器
     */
    private Random random = new Random();

    public BloomFilter(int expectedNumberOfElements) {
        if (expectedNumberOfElements > this.expectedNumberOfElements) {
            this.expectedNumberOfElements = expectedNumberOfElements;
        }

        // 根据公式计算哈希函数数量
        this.numberOfHashFunctions = (int) (Math.round(bitSetSize / expectedNumberOfElements) * Math.log(2.0));
        // 创建位数组并初始化所有位为0
        this.bitSet = new BitSet(bitSetSize);
    }

    public void add(Object element) {
        // 对元素进行多次哈希,并将对应的位设置为1
        for (int i = 0; i < numberOfHashFunctions; i++) {
            long hash = computeHash(element.toString(), i);
            int index = getIndex(hash);
            bitSet.set(index, true);
        }
    }

    public boolean contains(Object element) {
        // 对元素进行多次哈希,并检查所有哈希值所对应的位是否都被设置为1
        for (int i = 0; i < numberOfHashFunctions; i++) {
            long hash = computeHash(element.toString(), i);
            int index = getIndex(hash);
            if (!bitSet.get(index)) {
                return false;
            }
        }
        return true;
    }

    private int getIndex(long hash) {
        // 将哈希值映射到数组的下标(需要确保下标非负)
        return Math.abs((int) (hash % bitSetSize));
    }

    private long computeHash(String element, int seed) {
        // 使用伪随机数生成器生成不同的哈希种子
        random.setSeed(seed);

        // 将元素转换为字节数组,并计算其哈希值
        byte[] data = element.getBytes();
        long hash = 0x7f52bed27117b5efL;

        for (byte b : data) {
            hash ^= random.nextInt();
            hash *= 0xcbf29ce484222325L;
            hash ^= b;
        }
        return hash;
    }
}
  1. 我这边主要是从MySQL中获取数据,加载到布隆过滤器中,并且每天进行一次更新。只供参考
@Component
@Slf4j
@EnableScheduling
public class UpdateBloomFilterTask {
    @Autowired
    private CommonService commonService;

    private final int PAGE_SIZE = 1000;
 	// 每天16点进行更新
    @Scheduled(cron = "0 0 16 * * ?")
    @Bean("bloomFilterClient")
    public BloomFilter update() {
        log.debug("bloomFilter init start");
        List<String> data = commonService.getXXX(1, PAGE_SIZE);
        BloomFilter bloomFilter = new BloomFilter(Math.toIntExact(data.size()));
        for (String element : data) {
            bloomFilter.add(element);
        }
        for (int i = 2; i <= data.getTotalPage(); i++) {
            data = richMsgBlacklistService.getBlacklist(i, PAGE_SIZE);
            for (String element : data) {
                bloomFilter.add(element);
            }
        }
        log.debug("bloomFilter init finish.");
        return bloomFilter;
    }
}

  1. 实现类进行使用
public class TestServiceImpl {
	@Resource(name = "bloomFilterClient")
    private BloomFilter bloomFilter;
	public boolean testBloomFilter(String str) {
		return bloomFilter.contains(str);
	}
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值