后端、算法和数据库领域中的Bitmap(位图)

后端、算法和数据库领域中的Bitmap(位图)是一种非常精妙的数据结构。 简单来说,Bitmap是利用计算机中最小的单位—Bit(位/比特)—来存放数据结构的一种技术。

1. 核心原理:它是如何工作的?

通常我们存储一个数字,使用int类型需要占用4个字节(32bit)。而在Bitmap中,我们只用1个bit来表示这个数字是否存在。

  • 映射规则:我们申请一块连续的内存(bit数组)。数组的下标(Index)代表数据的值(比如用户的ID),而该位上的值(0或1)代表状态(比如“存在/不存在”、“未签到/已签到”)。
  • 例子:假如我们要记录ID为1、4、6的用户已签到。
    • 第1位为1
    • 第4位为1
    • 第6位为1
    • 其它为默认为0 空间对比:如果我们要存储1亿个用户的签到状态:
  • 使用Set/List(int):1亿 4字节 381 MB
  • 使用Bitmap:1亿 bits 12.5 MB
  • 结论:空间节省了约30倍。

2. Bitmap主要用来干什么?(应用场景)

Bitmap最擅长处理海量数据的布尔状态(Yes/No)统计和查找 A.用户行为统计(活跃度/签到) 互联网大厂(如使用Redis)最常用的场景。

  • 场景:统计App的日活(DAU)、月活(MAU),或者用户连续签到记录。
  • 做法:每一天作为一个Bitmap key,用户ID作为offset。

B.快速去重与排序(海量整数)

  • 场景:给你40亿个不重复的乱序整数,如何快速判断某个数是否存在?或者对他们进行排序?
  • 做法:建立一个能覆盖最大整数范围的Bitmap。遍历数据,将对应位置设为1。
    • 查找:直接看该位是0还是1,时间复杂度
    • 排序:遍历Bitmap,输出所有为1的下标,即为有序序列。

C. 布隆过滤器(Bloom Filter) 这是Bitmap的进阶应用,用于解决缓存穿透的问题。

  • 原理:当数据极大(如URL去重、垃圾邮件黑名单)且允许极低误判率时,使用多个Hash函数将数据映射到Bitmap的不同位置。
  • 作用:能够极快告诉你:“这个数据一定不存在,或者可能存在”。

D.权限与标签系统

  • 场景:Linux文件权限(rwx对应421)或用户标签(如“男”、“90后”、“极客”)。
  • 做法:每一位代表一种权限或标签。通过位运算(AND、OR)快速判断用户是否具备某些复杂特征。

3. 优缺点分析

特性描述
优势极致省空间:相比普通存储节省几十倍内存。



极致速度:基于位运算,CPU 处理速度极快,时间复杂度通常为



方便的集合运算:求交集、并集、补集(AND, OR, XOR)非常高效。
劣势数据稀疏问题:如果只需存 ID 为 1 和 ID 为 1亿 的两个用户,Bitmap 仍需申请 1亿个 bit 的空间,中间全是 0,极其浪费。



只能存整数:无法直接存储字符串(需要先 Hash 成整数)。



不可逆:通常只知道“存在”,无法存储具体的复杂信息(如用户名)。

4. 进阶:Roaring Bitmap(咆哮位图)

为了解决Bitmap在数据稀疏(Sparse)时的空间浪费问题,业界普遍使用Roaring Bitmap。

  • 原理:它将大块的Bitmap切分成小的容器(Container)。
    • 如果数据密集,使用普通的Bitmap容器。
    • 如果数据稀疏,使用Array容器(只存数值本身)。
  • 应用:Elasticsearch、Spark、Hive、Lucene等大数据与搜索引擎底层都在广泛使用Roaring Bitmap来做索引优化。

图形图像领域的Bitmap

Android中的Bitmap

1. 它是做什么的?

在Android中,Bitmap是一张图片在内存中的表现形式。

  • 当你把一张.jpg.png图片加载到内存中准备显示在屏幕上时,它就会被解码成一个Bitmap对象。
  • 本质上是一个像素矩阵。每一个像素点都包含颜色信息(红、绿、蓝、透明度)。 简单理解:
  • 文件形式:JPG/PNG(经过压缩,体积小,CPU无法直接绘制)。
  • 内存形式:Bitmap(未压缩的像素点集合,体积大,可以直接交个GPU/CPU绘制到屏幕)。

2. 为什么Android开发者都很怕它?(内存杀手)

Bitmap时导致OOM崩溃的头号杀手。 为什么?因为它极其占用内存。 内存计算公式: 举个例子:假设你有一张拍摄的照片,分辨率是 (1080P),格式是标准的 ARGB_8888(每个像素占 4 字节)。

注意:

  • 硬盘上这张JPG可能只有200KB,因为JPG是压缩格式。
  • 但加载到内存变成Bitmap后,它会瞬间膨胀成8MB。
  • 如果在一个列表加载100张这样的图,瞬间就需要800MB内存,App直接就奔溃了。

总结:

  • 算法中用空间换时间(且空间也很小),Android中用空间换画质。