package com.company.BloomFilter;
/*
* 用来查找是否存在某个元素 在尽可能少的内存下
* HashSet和HashMap的速度狠快,但是对于空间的利用率不是很高效
*/
public class BloomFilter<T> {
// 二进制位的长度
private int bitSize;
// 哈希函数的个数
private int hashSize;
private long[] bits;
/**
* @param n 数据规模
* @param p 误判率 取值范围(0,1)
* @throws IllegalAccessException
*/
public BloomFilter(int n, double p) throws IllegalAccessException {
if (n <= 0 || p <= 0 || p >= 1) {
throw new IllegalAccessException("wrong n or p");
}
double ln2 = Math.log(2);
// 求出二进制位的长度
this.bitSize = (int) (-(n * Math.log(p)) / (ln2 * ln2));
this.hashSize = (int) (bitSize * ln2 / n);
bits = new long[(bitSize + Long.SIZE - 1) / Long.SIZE];
}
/**
*
* @param value
* @return 是否存在某个元素
* @throws IllegalAccessException
* 先根据hashcode得到索引在long数组中的那一截,然后判断在当前long的哪一位
*/
public boolean contains(T value) throws IllegalAccessException{
nullCheck(value);
int hash1 = value.hashCode();
int hash2 = hash1 >>> 16;
for (int i = 0; i <= hashSize; i++) {
int combinedHash = hash1 + (i * hash2);
if (combinedHash < 0) {
combinedHash = ~combinedHash;
}
int index = combinedHash % bitSize ;
if (!getBit(index)) {
return false;
}
}
return true;
}
/**
* @param value
* @return 添加某个元素是否成功
* @throws IllegalAccessException
* 先根据hashcode得到索引在long数组中的那一截,然后判断在当前long的哪一位
*/
public boolean put(T value) throws IllegalAccessException {
nullCheck(value);
int hash1 = value.hashCode();
int hash2 = hash1 >>> 16;
boolean result = false;
for (int i = 0; i <= hashSize; i++) {
int combinedHash = hash1 + (i * hash2);
if (combinedHash < 0) {
combinedHash = ~combinedHash;
}
int index = combinedHash % bitSize;
if (setBit(index)){
result = true;
}
}
return result;
}
private boolean setBit(int index) {
long value = bits[index / Long.SIZE];
int bitValue = 1 << (index % Long.SIZE);
bits[index / Long.SIZE] = value | bitValue;
return (value & bitValue) == 0;
}
private boolean getBit(int index) {
int i = index / Long.SIZE ;
int innerIndex = (index % Long.SIZE);
return (bits[i] &( 1 << innerIndex)) != 0;
}
private void nullCheck(T value) throws IllegalAccessException {
if (value == null) {
throw new IllegalAccessException("Value must not be null !");
}
}
public static void main(String[] args) throws IllegalAccessException {
BloomFilter<Integer> bloomFilter = new BloomFilter<>(1_00_0000,0.01);
bloomFilter.put(12314123);
System.out.println(bloomFilter.contains(12314123));
}
}
03-06
290
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交