Java位图Bitmap从入门到实战应用详解

 更新时间:2025年09月11日 08:30:13   作者:码里看花‌  
位图(Bitmap)作为位运算的经典应用之一,通过巧妙地利用二进制位来表示数据的存在性或状态,实现了对大规模数据的高效存储与处理,这篇文章主要介绍了Java位图Bitmap从入门到实战应用的相关资料,需要的朋友可以参考下

导语:

位图(Bitmap)是一种高效存储和操作大量布尔值的数据结构。本文将从基础概念讲起,逐步深入位图的原理、应用场景及Java实现,助你轻松掌握这一高频面试知识点。

一、什么是位图?

位图(Bitmap) 是一种利用二进制位(0或1)来存储数据的数据结构。每个二进制位代表一个状态,常用于高效处理存在性判断去重签到统计等场景。

传统方案 vs 位图

  • 传统方案:使用boolean数组存储数据,每个元素占1字节(8位)。

  • 位图方案:每个元素仅占1位,空间利用率提升8倍

示例:存储1000万个用户的签到状态

  • boolean[]需要约10MB(10000000 / 1024 / 1024 ≈ 9.54MB)

  • 位图仅需约1.25MB(10000000 / 8 / 1024 / 1024 ≈ 1.19MB)

二、位图核心原理

1. 存储结构

  • 使用连续的内存块(如int[]long[]数组)存储位数据。

  • 计算位置:确定元素在数组中的索引和偏移量。

    • 索引元素值 / 32(int占32位)

    • 偏移元素值 % 32

2. 核心操作

  • 设置位:将指定位置为1

  • 清除位:将指定位置为0

  • 查询位:判断指定位置是否为1

三、位图应用场景

1. 用户签到统计

  • 用位图的每一位代表用户某天是否签到。

  • 每月签到仅需31位,全年仅需365位。

2. 数据去重

  • 快速判断元素是否存在,避免重复插入。

3. 布隆过滤器

  • 位图是布隆过滤器实现的基础结构,用于高效判断元素可能存在绝对不存在

四、Java位图实现

1. 使用BitSet类

Java内置的BitSet类提供了位图操作API。

import java.util.BitSet;

public class BitSetDemo {
    public static void main(String[] args) {
        BitSet bitmap = new BitSet(100); // 初始化100位的位图
        
        // 设置第5位为1(签到)
        bitmap.set(5);
        
        // 检查第5位是否为1
        System.out.println("第5天是否签到:" + bitmap.get(5)); // true
        
        // 清除第5位
        bitmap.clear(5);
        System.out.println("清除后:" + bitmap.get(5)); // false
    }
}

2. 手动实现位图

通过int[]数组和位运算手动实现位图:

public class CustomBitmap {
    private int[] bits; // 存储位数据
    
    public CustomBitmap(int capacity) {
        // 计算需要多少个int来存储capacity位
        bits = new int[(capacity >> 5) + 1]; // capacity/32 +1
    }
    
    // 设置位
    public void set(int pos) {
        int index = pos >> 5;       // 计算数组索引(等价于pos/32)
        int offset = pos & 0x1F;    // 计算偏移量(等价于pos%32)
        bits[index] |= (1 << offset); // 将指定位置1
    }
    
    // 清除位
    public void clear(int pos) {
        int index = pos >> 5;
        int offset = pos & 0x1F;
        bits[index] &= ~(1 << offset); // 将指定位清0
    }
    
    // 查询位
    public boolean get(int pos) {
        int index = pos >> 5;
        int offset = pos & 0x1F;
        return (bits[index] & (1 << offset)) != 0;
    }

    public static void main(String[] args) {
        CustomBitmap bitmap = new CustomBitmap(100);
        bitmap.set(10); // 设置第10位
        System.out.println("第10位状态:" + bitmap.get(10)); // true
        bitmap.clear(10);
        System.out.println("清除后:" + bitmap.get(10)); // false
    }
}

五、注意事项与优化

1. 稀疏数据处理

  • 当数据非常稀疏时(如存储1和1,000,000两个值),位图可能浪费空间。

  • 解决方案:使用压缩位图(如Roaring Bitmap)。

2. 线程安全

  • BitSet非线程安全!多线程环境下需使用Collections.synchronized包装或自定义锁。

3. 动态扩容

  • BitSet自动扩容,手动实现的位图需处理数组扩容逻辑。

六、总结

位图通过将每个元素压缩到1位,大幅节省存储空间,尤其适合处理海量布尔值场景。合理使用位图,可显著提升程序性能。但需根据数据分布选择合适方案,避免空间浪费。

到此这篇关于Java位图Bitmap从入门到实战应用的文章就介绍到这了,更多相关Java位图Bitmap详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • IntelliJ IDEA 热部署插件JRebel的使用

    IntelliJ IDEA 热部署插件JRebel的使用

    这篇文章主要介绍了IntelliJ IDEA 热部署插件JRebel的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • mybatis-plus批量更新太慢该如何解决详解

    mybatis-plus批量更新太慢该如何解决详解

    这篇文章主要给大家介绍了关于mybatis-plus批量更新太慢该如何解决的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2023-03-03
  • mybatis输入映射和输出映射实例详解

    mybatis输入映射和输出映射实例详解

    这篇文章主要介绍了mybatis输入映射和输出映射,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • SpringBoot Web工程同时启动多个HTTP端口的方法

    SpringBoot Web工程同时启动多个HTTP端口的方法

    本文介绍了在SpringbootWeb工程中如何配置多个HTTP端口,分别以Tomcat、Jetty和Undertow为例,通过修改配置文件和编写配置类实现多端口启动,并提供了详细的代码供读者参考,需要的朋友可以参考下
    2026-04-04
  • SpringBoot自动化配置原理和自定义starter方式

    SpringBoot自动化配置原理和自定义starter方式

    SpringBoot自动配置机制主要通过-spring-boot-starter和-spring-boot-autoconfigure创建自定义starter模块,使用EnableAutoConfiguration注解加载自动配置类,启动类通过创建Spring容器完成自动化装配
    2026-04-04
  • Java如何判断一个字符串是否包含某个字符串

    Java如何判断一个字符串是否包含某个字符串

    这篇文章主要给大家介绍了关于Java如何判断一个字符串是否包含某个字符串的相关资料,在实际编程中,经常需要判断一个字符串中是否包含某个子串,需要的朋友可以参考下
    2023-07-07
  • ServletWebServerApplicationContext创建Web容器Tomcat示例

    ServletWebServerApplicationContext创建Web容器Tomcat示例

    这篇文章主要为大家介绍了ServletWebServerApplicationContext创建Web容器Tomcat示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Java编程子类能否重写父类的静态方法探索

    Java编程子类能否重写父类的静态方法探索

    关于子类能否重写父类的静态方法,对像我这种初级的编程爱好者来说仍是值得讨论的一件事,下面我们通过具体实例,对此问题进行简单的探索。
    2017-10-10
  • Java中两种抛出异常的方式示例详解

    Java中两种抛出异常的方式示例详解

    在Java中有两种抛出异常的方式,一种是throw,直接抛出异常,另一种是throws,间接抛出异常,本文给大家详细说明java中两种抛出异常的方式,感兴趣的朋友一起看看吧
    2023-08-08
  • Java一维数组和二维数组元素默认初始化值的判断方式

    Java一维数组和二维数组元素默认初始化值的判断方式

    这篇文章主要介绍了Java一维数组和二维数组元素默认初始化值的判断方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08

最新评论