我想知道在哪里可以找到Bloom过滤器的实现,并提供有关散列函数选择的一些解释。
此外,我还有以下问题:
1)已知布隆过滤器具有误报。是否可以通过使用两个过滤器来减少它们,一个用于已使用的元素,一个用于未使用的元素(假设该集合是有限的并且已知先验)并比较两者?
2)CS文献中还有其他类似的算法吗?
答案 0 :(得分:1)
我的直觉是,通过使用反滤波器占用的额外空间来扩展正滤波器,可以更好地减少误报。
至于资源方面,3月8日从my course syllabus引用的论文会很有用。
答案 1 :(得分:0)
可以从here找到Bloom过滤器的Java实现。如果您无法查看,我将粘贴以下代码(中文注释)。
import java.util.BitSet;
publicclass BloomFilter
{
/* BitSet初始分配2^24个bit */
privatestaticfinalint DEFAULT_SIZE =1<<25;
/* 不同哈希函数的种子,一般应取质数 */
privatestaticfinalint[] seeds =newint[] { 5, 7, 11, 13, 31, 37, 61 };
private BitSet bits =new BitSet(DEFAULT_SIZE);
/* 哈希函数对象 */
private SimpleHash[] func =new SimpleHash[seeds.length];
public BloomFilter()
{
for (int i =0; i < seeds.length; i++)
{
func[i] =new SimpleHash(DEFAULT_SIZE, seeds[i]);
}
}
// 将字符串标记到bits中
publicvoid add(String value)
{
for (SimpleHash f : func)
{
bits.set(f.hash(value), true);
}
}
//判断字符串是否已经被bits标记
publicboolean contains(String value)
{
if (value ==null)
{
returnfalse;
}
boolean ret =true;
for (SimpleHash f : func)
{
ret = ret && bits.get(f.hash(value));
}
return ret;
}
/* 哈希函数类 */
publicstaticclass SimpleHash
{
privateint cap;
privateint seed;
public SimpleHash(int cap, int seed)
{
this.cap = cap;
this.seed = seed;
}
//hash函数,采用简单的加权和hash
publicint hash(String value)
{
int result =0;
int len = value.length();
for (int i =0; i < len; i++)
{
result = seed * result + value.charAt(i);
}
return (cap -1) & result;
}
}
}
在设计布隆过滤器方面,布隆过滤器所需的哈希函数的数量可以在here中确定,同时引用Wikipedia article about Bloom filters,然后您会找到误差概率的部分。本节介绍散列函数的数量如何影响误报的概率,并为您提供从期望的预期概率确定 k 的公式。误报。
来自维基百科的文章:
显然,虚假的概率 正数减少为m(数字 数组中的位数增加,并且 增加为n(插入的数量) 元素)增加。对于给定的m和 n,k的值(散列数 函数)最小化 概率是
答案 2 :(得分:0)
使用Java 8功能实现Bloom过滤器非常容易。您只需要long[]
来存储这些位,以及一些哈希函数,您可以使用ToIntFunction<T>
来表示这些函数。我在doing this from scratch上做了简短的写作。
要注意的部分是从数组中选择正确的位。
public class BloomFilter<T> {
private final long[] array;
private final int size;
private final List<ToIntFunction<T>> hashFunctions;
public BloomFilter(long[] array, int logicalSize, List<ToIntFunction<T>> hashFunctions) {
this.array = array;
this.size = logicalSize;
this.hashFunctions = hashFunctions;
}
public void add(T value) {
for (ToIntFunction<T> function : hashFunctions) {
int hash = mapHash(function.applyAsInt(value));
array[hash >>> 6] |= 1L << hash;
}
}
public boolean mightContain(T value) {
for (ToIntFunction<T> function : hashFunctions) {
int hash = mapHash(function.applyAsInt(value));
if ((array[hash >>> 6] & (1L << hash)) == 0) {
return false;
}
}
return true;
}
private int mapHash(int hash) {
return hash & (size - 1);
}
public static <T> Builder<T> builder() {
return new Builder<>();
}
public static class Builder<T> {
private int size;
private List<ToIntFunction<T>> hashFunctions;
public Builder<T> withSize(int size) {
this.size = size;
return this;
}
public Builder<T> withHashFunctions(List<ToIntFunction<T>> hashFunctions) {
this.hashFunctions = hashFunctions;
return this;
}
public BloomFilter<T> build() {
return new BloomFilter<>(new long[size >>> 6], size, hashFunctions);
}
}
}
答案 3 :(得分:-1)
我认为我们应该看一下Bloom Filters的应用,而秘密在于名称,它是一个过滤器而不是数据结构。它主要用于通过检查项目是否不属于集合来节省资源。如果你想将误报最小化为0,你将不得不插入所有不属于集合的项目,因为设计良好的布隆过滤器没有假阴性,除了布隆过滤器将是巨大的和不实用的,也许只是将项目存储在跳过列表:)我写了一个关于Bloom Filters的简单教程,如果有人感兴趣的话。
http://techeffigy.wordpress.com/2014/06/05/bloom-filter-tutorial/