Bitmap
bitmap(位图)的数据结构
Java中的BitSet数据结构
01.Java中Bitset的使用
Java中原生的bitmap的实现: BitSet
BitSet 一个Bitset类创建一种特殊类型的数组来保存位值。BitSet中数组大小会随需要增加
BitSet定义了两个构造方法: BitSet() BitSet(int size)
BitSet的底层实现是使用long数组作为内部存储结构的
变为Bitset
cardinality( ) 返回此 BitSet 中设置为 true 的位数
//就是BitSet中存放的有效位的个数,如果有重复运算会进行自动去重
length() 返回此 BitSet 的"逻辑大小": BitSet 中最高设置位的索引加 1
size( ) 返回此 BitSet 表示位值时实际使用空间的位数
(即通过使用此BitSet表示位来分配给实际位数的内存)。128bit
说明: null 参数传递给 BitSet 中的任何方法都将导致 NullPointerException
基本操作
Bitmap的基本操作有: set() clear() flip()
初始化一个bitset,指定大小。
清空bitset。
反转某一指定位。
设置某一指定位。
获取某一位的状态。
当前bitset的bit总位数。
逻辑计算 and or andNot xor
排序: 按照顺序循环取出在BitSet存在的数,以此达到排序的目的
02. Bitset 源码:
recalculateWordsInUse(); wordsInUse 是检查当前的long数组中,实际使用的long的个数
checkInvariants();
这两个函数,是对bitset的内部状态进行维护和检查的函
Roaringbitmap
container是RBM新创造的概念:
ArrayContainer BitmapContainer RunContainer
具体的实现
开源工具类 JavaEWAH 或者 RoaringBitmap
开源工具实现-- EWAHCompressedBitmap(谷歌对Bitmap的实现)
<dependency>
<groupId>com.googlecode.javaewah</groupId>
<artifactId>JavaEWAH</artifactId>
<version>1.1.7</version>
</dependency>
开源工具实现
<dependency>
<groupId>org.roaringbitmap</groupId>
<artifactId>RoaringBitmap</artifactId>
<version>0.8.1</version>
</dependency>
1.Roaringbitmap
主要的操作 org.roaringbitmap.RoaringBitmap
主要使用 add remove bitmapOf()
and or xor
// 向r1中添加1、2、3、1000四个数字
RoaringBitmap r1 = RoaringBitmap.bitmapOf(1, 2, 3, 1000);
2. 位图位于内存映射文件中,则可以改用 org.roaringbitmap.buffer 包
ImmutableRoaringBitmap 和 MutableRoaringBitmap
public class MutableRoaringBitmap extends ImmutableRoaringBitmap
implements Cloneable, Serializable, Iterable<Integer>, Externalizable,
BitmapDataProvider, AppendableStorage<MappeableContainer> {}
从ByteBuffer创建ImmutableRoaringBitmap
ByteArrayOutputStream bos = new ByteArrayOutputStream()
ByteBuffer bb = ByteBuffer.wrap(bos.toByteArray());
ImmutableRoaringBitmap rrback1 = new ImmutableRoaringBitmap(bb);
3.,RoaringBitmap处理的是int类型的数据,但是在实际中我们使用的都是long类型的,可以使用Roaring64NavigableMap。
Roaring64NavigableMap
Roaring64NavigableMap也是使用拆分模式,将一个long类型数据,拆分为高32位与低32位,
高32位代表索引,低32位存储到对应RoaringBitmap中,其内部是一个TreeMap类型的结构,会按照signed或者unsigned进行排序,key代表高32位,value代表对应的RoaringBitmap。
应用场景
01.给定含有40亿个不重复的位于[0, 4294967295]区间内的整数的集合,如何快速判定某个数是否在该集合内?
正常Java int类型存储 2^32*4*8/8/2^10/2^10/2^10 = 16GB
一个bit位代表一个整数是否存在,可以计算出所占用的大小就是 2^32*1/8/2^10/2^10 = 512M
02.在3亿个整数中找出不重复的整数
03. 已知某个文件内包含一些电话号码,每个号码为8位数字,统计不同号码的个数
参考:
BitMap的原理和实现 https://www.cnblogs.com/myseries/p/10880641.html
https://github.com/RoaringBitmap/RoaringBitmap
Python: 实现bitmap数据结构 https://my.oschina.net/goal/blog/200347
RoaringBitmap精确去重 https://blog.csdn.net/lao000bei/article/details/105725579