BitMap与RoaringBitmap、JavaEWAH
本文主要介绍BitMap的算法思想,以及开源工具类JavaEWAH、RoaringBitmap的简单用法。
一、BitMap
介绍
BitMap使用bit位
,来标记元素对应的Value。该算法能够节省存储空间
。
假设一个场景,要存0-7以内的数字[3,5,6,1,2],尽可能的节省空间。
一种思路就是单纯使用数组存储,但如果数据量放大百万倍甚至千万倍呢,数组的所占用的内存会非常大。
另一种思路是使用BitMap
。
表示[3,5,7,1,2],我们可以用8bit的空间来存储,每个数字都在对应的位置中以1的方式表示。
位置7 | 位置 6 | 位置 5 | 位置 4 | 位置 3 | 位置 2 | 位置 1 | 位置 0 |
---|---|---|---|---|---|---|---|
1 | 0 | 1 | 0 | 1 | 1 | 1 | 0 |
若将上述BitMap看作是存储用户的标签
,如信用卡逾期
标签,位置看成用户ID
,则若需要查询哪些用户有信用卡逾期的行为(标签),就非常容易查询统计了。
二、RoaringBitmap
文档中怎么说?
Bitsets, also called bitmaps, are commonly used as fast data structures. Unfortunately, they can use too much memory. To compensate, we often use compressed bitmaps.
BitMap通常被用作快速查询的数据结构,但它太占内存了。解决方案是,对BitMap进行压缩
。
Roaring bitmaps are compressed bitmaps which tend to outperform conventional compressed bitmaps such as WAH, EWAH or Concise. In some instances, roaring bitmaps can be hundreds of times faster and they often offer significantly better compression. They can even be faster than uncompressed bitmaps.
Roaring bitmaps是一种超常规的压缩BitMap。它的速度比未压缩的BitMap
快上百倍。
简单使用
引入依赖
<dependency>
<groupId>org.roaringbitmap</groupId>
<artifactId>RoaringBitmap</artifactId>
<version>0.8.1</version>
</dependency>
测试代码
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestRoaringbitmap {
@Test
public void test(){
//向rr中添加1、2、3、1000四个数字
RoaringBitmap rr = RoaringBitmap.bitmapOf(1,2,3,1000);
//创建RoaringBitmap rr2
RoaringBitmap rr2 = new RoaringBitmap();
//向rr2中添加10000-12000共2000个数字
rr2.add(10000L,12000L);
//返回第3个数字是1000,第0个数字是1,第1个数字是2,则第3个数字是1000
rr.select(3);
//返回value = 2 时的索引为 1。value = 1 时,索引是 0 ,value=3的索引为2
rr.rank(2);
//判断是否包含1000
rr.contains(1000); // will return true
//判断是否包含7
rr.contains(7); // will return false
//两个RoaringBitmap进行or操作,数值进行合并,合并后产生新的RoaringBitmap叫rror
RoaringBitmap rror = RoaringBitmap.or(rr, rr2);
//rr与rr2进行位运算,并将值赋值给rr
rr.or(rr2);
//判断rror与rr是否相等,显然是相等的
boolean equals = rror.equals(rr);
if(!equals) throw new RuntimeException("bug");
// 查看rr中存储了多少个值,1,2,3,1000和10000-12000,共2004个数字
long cardinality = rr.getLongCardinality();
System.out.println(cardinality);
//遍历rr中的value
for(int i : rr) {
System.out.println(i);
}
//这种方式的遍历比上面的方式更快
rr.forEach((Consumer<? super Integer>) i -> {
System.out.println(i.intValue());
});
}
}
三、JavaEWAH
引入依赖
<dependency>
<groupId>com.googlecode.javaewah</groupId>
<artifactId>JavaEWAH</artifactId>
<version>1.1.6</version>
</dependency>
测试代码
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestJavaEWAH {
@Test
public void test(){
EWAHCompressedBitmap ewahBitmap1 = EWAHCompressedBitmap.bitmapOf(0, 2, 55, 64, 1 << 30);
EWAHCompressedBitmap ewahBitmap2 = EWAHCompressedBitmap.bitmapOf(1, 3, 64,1 << 30);
//bitmap 1: {0,2,55,64,1073741824}
System.out.println("bitmap 1: " + ewahBitmap1);
//bitmap 2: {1,3,64,1073741824}
System.out.println("bitmap 2: " + ewahBitmap2);
//是否包含value=64,返回为true
System.out.println(ewahBitmap1.get(64));
//获取value的个数,个数为5
System.out.println(ewahBitmap1.cardinality());
//遍历所有value
ewahBitmap1.forEach(integer -> {
System.out.println(integer);
});
//进行位或运算
EWAHCompressedBitmap orbitmap = ewahBitmap1.or(ewahBitmap2);
//返回bitmap 1 OR bitmap 2: {0,1,2,3,55,64,1073741824}
System.out.println("bitmap 1 OR bitmap 2: " + orbitmap);
//memory usage: 40 bytes
System.out.println("memory usage: " + orbitmap.sizeInBytes() + " bytes");
//进行位与运算
EWAHCompressedBitmap andbitmap = ewahBitmap1.and(ewahBitmap2);
//返回bitmap 1 AND bitmap 2: {64,1073741824}
System.out.println("bitmap 1 AND bitmap 2: " + andbitmap);
//memory usage: 32 bytes
System.out.println("memory usage: " + andbitmap.sizeInBytes() + " bytes");
//序列化与反序列化
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ewahBitmap1.serialize(new DataOutputStream(bos));
EWAHCompressedBitmap ewahBitmap1new = new EWAHCompressedBitmap();
byte[] bout = bos.toByteArray();
ewahBitmap1new.deserialize(new DataInputStream(new ByteArrayInputStream(bout)));
System.out.println("bitmap 1 (recovered) : " + ewahBitmap1new);
} catch (IOException e) {
e.printStackTrace();
}
}
}
参考文档
[1]: BitMap算法详解
[2]: 漫画:Bitmap算法 整合版
[3]: RoaringBitmap GitHub项目文档
[4]: JavaEWAH GitHub项目文档
BitMap与RoaringBitmap、JavaEWAH的更多相关文章
- bitmap技术解析:redis与roaringBitmap
bitmap的表象意义是,使用一个01标识位来表示是否的状态,可以达到节省空间和高效判定的效果.在我们的实际工作中,也有着许多的应用场景,相信了解bitmap定会给你带来一些额外的收获. 1. bit ...
- [转载] Bitmap的秘密
转载自http://www.infoq.com/cn/articles/the-secret-of-bitmap/ 之前已经参加过几次QCon峰会,不过今年QCon 2014 上海峰会对我来说比较特别 ...
- Bitmap的秘密
作者: 周海鹏 来源: infoQ 发布时间: 2015-02-13 11:26 阅读: 4999 次 推荐: 10 原文链接 [收藏] 之前已经参加过几次QCon峰会,不过今年QCo ...
- 【算法】BitMap
转自:https://www.seoxiehui.cn/article-45186-1.html 需求: 为满足用户标签的统计需求,小灰利用Mysql设计了如下的表结构,每一个维度的标签都对应着Mys ...
- 在MaxCompute中利用bitmap进行数据处理
很多数据开发者使用bitmap技术对用户数据进行编码和压缩,然后利用bitmap的与/或/非的极速处理速度,实现类似用户画像标签的人群筛选.运营分析的7日活跃等分析.本文给出了一个使用MaxCompu ...
- JDK中的BitMap实现之BitSet源码分析
前提 本文主要内容是分析JDK中的BitMap实现之java.util.BitSet的源码实现,基于JDK11编写,其他版本的JDK不一定合适. 文中的图比特低位实际应该是在右边,但是为了提高阅读体验 ...
- BitMap算法知识笔记以及在大数据方向的使用
概述 所谓的BitMap算法就是位图算法,简单说就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来存储数据,因此可以大大节省存储空间,这是很常用的 ...
- [翻译]开发文档:android Bitmap的高效使用
内容概述 本文内容来自开发文档"Traning > Displaying Bitmaps Efficiently",包括大尺寸Bitmap的高效加载,图片的异步加载和数据缓存 ...
- 【开源毕设】一款精美的家校互动APP分享——爱吖校推 [你关注的,我们才推](持续开源更新3)附高效动态压缩Bitmap
一.写在前面 爱吖校推如同它的名字一样,是一款校园类信息推送交流平台,这么多的家校互动类软件,你选择了我,这是我的幸运.从第一次在博客园上写博客到现在,我一次一次地提高博文的质量和代码的可读性,都是为 ...
随机推荐
- Redis的概述、优势和安装部署
Redis概述 Redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的应用程序的完美解决方案. Redis从它的许多竞争继承来的三个主要特点: Redis数据库完全在内存中,使 ...
- 【Luogu P3371&P4779】【模板】单源最短路径(线段树优化Dijkstra)
线段树优化$\rm dijkstra$ 线段树每个节点维护$[l,r]$中$dist$最小的点,删除则把该点$dist$赋值为$+\infty$,然后更新该点影响到的线段树上的其他节点即可. 可以得到 ...
- Android之操作相册
获取手机中的图片的绝对路径并且区分出每个文件夹下的路径: 存放图片绝对路径的文件夹的名字和存放绝对路径的List 实体类如下: import java.util.ArrayList; import j ...
- C++ bitset类的使用与简介
有些程序要处理二进制位的有序集,每个位可能包含的是0(关)或1(开)的值.位是用来保存一组项或条件的yes/no信息(有时也称标志)的简洁方法.标准库提供了bitset类使得处理位集合更容易一些.要使 ...
- UVALive 5099 Nubulsa Expo 全局最小割问题
B - Nubulsa Expo Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit S ...
- linux下编译lua库
编辑MakeFile INSTALL_TOP= /usr/local修改为目标install位置 执行 make linux make install 如果提示依赖libreadline 可以直接a ...
- Codeforeces 954C Matrix Walk
题目大意 考虑一个 $x\times y$ 的矩阵 $A_{x\times y}$ ,$A_{i,j} = (i-1)x+y$ . 从矩阵中的某个位置出发,每次可向上下左右移动一步,每到一个位置,记录 ...
- 本文将介绍“数据计算”环节中常用的三种分布式计算组件——Hadoop、Storm以及Spark。
本文将介绍“数据计算”环节中常用的三种分布式计算组件——Hadoop.Storm以及Spark. 当前的高性能PC机.中型机等机器在处理海量数据时,其计算能力.内存容量等指标都远远无法达到要求.在大数 ...
- SGU 乱搞日志
SGU 100 A+B :太神不会 SGU 101 Domino: 题目大意:有N张骨牌,两张骨牌有两面有0到6的数字,能相连当且仅当前后数字相同,问能否有将N张骨牌连接的方案?思路:裸的欧拉回路,注 ...
- vi 使用介绍
参考 <<vi编辑器使用介绍>>文本编辑器有很多,比如图形模式的gedit.kwrite.OpenOffice ,文本模式下的编辑器有vi.vim(vi的增强版本)和nano, ...