`
qianshangding
  • 浏览: 127889 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

BitSet和布隆过滤器(Bloom Filter)

 
阅读更多

布隆过滤器

Bloom Filter 是由Howard Bloom 在 1970 年提出的二进制向量数据结构,它具有很好的空间和时间效率,被用来检测一个元素是不是集合中的一个成员。如果检测结果为是,该元素不一定在集合中;但如果检测结果为否,该元素一定不在集合中。因此Bloom filter具有100%的召回率。这样每个检测请求返回有“在集合内(可能错误)”和“不在集合内(绝对不在集合内)”两种情况,可见 Bloom filter 是牺牲了正确率和时间以节省空间。

当然布隆过滤器也有缺点,主要是误判的问题,随着数据量的增加,误判率也随着增大,解决办法:可以建立一个列表,保存哪些数值是容易被误算的。

Bloom Filter最大的特点是不会存在false negative,即:如果contains()返回false,则该元素一定不在集合中,但会存在一定的true negative,即:如果contains()返回true,则该元素可能在集合中。

Bloom Filter在很多开源框架都有实现,例如:

Elasticsearch:org.elasticsearch.common.util.BloomFilter

guava:com.google.common.hash.BloomFilter

Hadoop:org.apache.hadoop.util.bloom.BloomFilter(基于BitSet实现)

有兴趣可以看看源码。

BitSet的基本原理

最后再了解一下BitSet的基本原理,BitSet是位操作的对象,值只有0或1,内部实现是一个long数组,初始只有一个long数组,所以BitSet最小的size是64,当存储的数据增加,初始化的Long数组已经无法满足时,BitSet内部会动态扩充,最终内部是由N个long来存储,BitSet的内部扩充和List,Set,Map等得实现差不多,而且都是对于用户透明的。
1G的空间,有 8*1024*1024*1024=8589934592bit,也就是可以表示85亿个不同的数。

BitSet用1位来表示一个数据是否出现过,0为没有出现过,1表示出现过。在long型数组中的一个元素可以存放64个数组,因为Java的long占8个byte=64bit,具体的实现,看看源码:

首先看看set方法的实现:

public void set(int bitIndex) {
   if (bitIndex < 0)   //set的数不能小于0
        throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);

   int wordIndex = wordIndex(bitIndex);//将bitIndex右移6位,这样可以保证每64个数字在long型数组中可以占一个坑。
   expandTo(wordIndex);

   words[wordIndex] |= (1L << bitIndex); // Restores invariants
   checkInvariants();
}
get命令实现:
public boolean get(int bitIndex) {
   if (bitIndex < 0)
       throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);

   checkInvariants();

   int wordIndex = wordIndex(bitIndex);//和get一样获取数字在long型数组的那个位置。
   return (wordIndex < wordsInUse)
        && ((words[wordIndex] & (1L << bitIndex)) != 0);//在指定long型数组元素中获取值。
}
BitSet容量动态扩展:

private void ensureCapacity(int wordsRequired) {
 if (words.length < wordsRequired) {
  // Allocate larger of doubled size or required size
 int request = Math.max(2 * words.length, wordsRequired);//默认是扩大一杯的容量,如果传入的数字大于两倍的,则以传入的为准。
        // wordsRequired = 传入的数值右移6位 + 1
 words = Arrays.copyOf(words, request);
  sizeIsSticky = false;
 }
}

BitSet中实现了Cloneable接口,并定义在表中列出的方法:

SN Methods with 描述
1 void and(BitSet bitSet)
与运算调用的内容BitSet中对象与那些指定bitSet。结果存放到调用对象。
2 void andNot(BitSet bitSet)
对于bitSet每1位,在调用BitSet中的相应位清零。
3 int cardinality( )
返回BitSet的容量。
4 void clear( )
所有位清零。
5 void clear(int index)
index指定的位清零。
6 void clear(int startIndex, int endIndex)
将从startIndex到endIndex清零。
7 Object clone( )
重复调用BitSet中对象。
8 boolean equals(Object bitSet)
返回true如果调用位设置相当于一个在bitSet通过。否则,该方法返回false。
9 void flip(int index)
逆转由index指定的位。
10 void flip(int startIndex, int endIndex)
反转将从startIndex位到endIndex.
11 boolean get(int index)
返回指定索引处的位的当前状态。
12 BitSet get(int startIndex, int endIndex)
返回一个BitSet中,它包含的比特将从startIndex到endIndex.1。调用对象不被改变。
13 int hashCode( )
返回调用对象的哈希代码。
14 boolean intersects(BitSet bitSet)
如果至少有一个对调用对象和bitSet内相应位为1,则返回true。
15 boolean isEmpty( )
返回true如果在调用对象中的所有位均为零。
16 int length( )
返回到持有调用BitSet中的内容所需的比特数。这个值是由最后1位的位置决定的。
17 int nextClearBit(int startIndex)
返回下个清零位的索引,(即,下一个零位),从由startIndex指定的索引开始
18 int nextSetBit(int startIndex)
返回下一组位(即,下一个1比特)的索引,从由startIndex指定的索引开始。如果没有位被设置,则返回1。
19 void or(BitSet bitSet)
OR值调用的内容BitSet中对象,通过BitSet指定。结果被放置到调用对象。
20 void set(int index)
设置由index指定的位。
21 void set(int index, boolean v)
设置由index指定在v. true为传递的值的位设置位,false则清除该位。
22 void set(int startIndex, int endIndex)
设置位将从startIndex到endIndex.1。
23 void set(int startIndex, int endIndex, boolean v)
设置位从startIndex到endIndex.1,在真正传递的值v设置位,清除位为false。
24 int size( )
返回位在调用BitSet中对象的数量。
25 String toString( )
返回字符串相当于调用BitSet中的对象。
26 void xor(BitSet bitSet)

在异或调用BitSet中对象的内容与由BitSet指定。结果存放到调用对象。


BloomFilter的使用场景

1,爬虫的URL过滤。

2,日志分析

3,用户数统计等等等

总之使用布隆过滤器应该是可能容忍小概率误判的场景,不然慎用。。。

分享到:
评论

相关推荐

    java实现的布隆过滤器算法

    在提供的压缩包文件`Bloom Filter`中,可能包含了具体的Java实现代码,你可以通过阅读和分析这些代码来深入理解布隆过滤器的工作原理和Java实现细节。此外,还可以通过测试不同参数组合下的性能,进一步了解布隆过滤...

    布隆过滤器之C++实现

    C++实现的布隆过滤器,其中使用到的bitset也是自己简单实现的一个BitContainer。可以处理千万条到亿条记录的存在性判断。做成dll可以在很多场合使用,如自己写爬虫,要判断一个url是否已经访问过,判断一个单词是否...

    布隆过滤器(Bloom Filter)的Java实现方法

    【布隆过滤器(Bloom Filter)的Java实现】 布隆过滤器是一种空间效率极高的概率型数据结构,用于判断一个元素是否可能在一个集合中。它可能会产生误报(false positive),但不会产生漏报(false negative)。在Java...

    C++ 数据结构之布隆过滤器

    布隆过滤器(Bloom Filter)是一种空间效率很高的随机数据结构,可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,但缺点是有一定的误识别率和删除错误。 一、历史背景...

    bloom:布隆过滤器

    盛开 编译安装 $ git clone https://github.com/abenhlal/bloom.git $ cd bitset $ mkdir build $ cd build $ cmake .. $ make $ make test $ sudo make install ... bloom_filter_t *b1 = bloom_new (hash_

    bloomfilter:用Golang编写的Bloomfilter,包括旋转和RPC

    布隆过滤器是一种节省空间的概率数据结构,用于确定元素是否属于集合。 布隆过滤器允许错误肯定(可能在集合中),但不允许错误否定(绝对不在集合中)。 如果您不熟悉Bloomfilters,请阅读《 。 bloomfilter软件包...

    Spell-Checker-using-Bloom-Filter:应用布隆过滤器检查存储在文件中的单词的拼写

    布隆过滤器是一种概率数据结构,常用于空间效率极高的数据去重和存在性查询。在拼写检查器中,它的作用是高效地检测单词是否存在于一个预定义的词汇库中,而不需要实际存储所有词汇。这种方法对于处理大量词汇且内存...

    十道海量数据处理面试题(卷).docx

    这些题目覆盖了海量数据处理的关键技术,包括数据结构(如Trie树、Bloom Filter、Bitset)、排序算法(如基数排序、快速排序)、分布式计算框架(如MapReduce)、空间效率优化(如Top-K、布隆过滤器)等。...

    十道海量数据处理面试题(卷).doc

    使用布隆过滤器(Bloom Filter)初步判断可能存在共同 url,再使用 MapReduce 对两个文件进行交集操作。 5. 在 2.5 亿个整数中找出不重复的整数: 利用位图(Bitset)表示,或者使用 Hash 表结合布隆过滤器,如果...

    面试题目-大数据量海量数据处理.pdf

    1. **URL共现问题**:这是一个典型的集合交集问题,可以通过布隆过滤器(Bloom Filter)或MapReduce模型来解决。布隆过滤器可以在有限的内存空间内判断元素是否存在,但存在误判可能。MapReduce则可以分布式地处理大...

    RoaringBitmap.zip

    它在处理大规模数据集时能够提供显著的性能优势,比传统的布隆过滤器(Bloom Filter)和Java内置的BitSet类更为高效。RoaringBitmap的设计目标是减少内存占用并加快位操作的速度。 RoaringBitmap的核心思想是将一个...

    Redisson 使用手册.pdf

    4. 分布式对象:Redisson提供了多种分布式对象,如BitSet、原子整长形(AtomicLong)、原子双精度浮点(AtomicDouble)、话题(订阅分发)、布隆过滤器(Bloom Filter)等。 5. 分布式集合:Redisson提供了多种...

    libakio:我写了一些有用的算法和数据结构或库

    3. **布隆过滤器(Bloom Filter)**: 布隆过滤器是一种概率数据结构,用于判断一个元素是否可能存在于一个大型集合中。它利用了多个独立哈希函数减少空间需求,但可能会有误报(false positive),不会漏报(false...

    Locality-Sensitive-Hashing

    4. **优化技巧**:如使用BitSet减少存储空间,或者使用布隆过滤器(Bloom Filter)来初步筛选潜在的相似项,减少不必要的计算。 在`Locality-Sensitive-Hashing-master`这个项目中,我们可以期待看到以下内容: 1. **...

    listoverlap2

    对于大数据量,可能需要考虑更高效的算法,如布隆过滤器(Bloom Filter)或位图(Bitset)。 6. **编程语言**:尽管没有明确指出,但根据文件名,这个项目可能使用Python,因为Python在处理列表和集合操作时非常...

    60道关于Redis的常见面试题.pdf

    - 使用布隆过滤器(Bloom Filter)预先判断数据是否存在。 - 对空结果也进行缓存,但设置较短的有效时间。 #### 4. 介绍 Redis 的持久化机制以及对比它们之间的区别。 - **RDB(Redis Database Backup)**: - 定期...

Global site tag (gtag.js) - Google Analytics