【Java】使用位运算将多个 boolean 类型的变量压缩成一个 int 类型的值

项目需求

为了减少上传的数据量,用一个int类型的数据表示几个boolean类型的变量,用每一位的0代表false,用1代表true,这样一个int值可以代表多个这种类型的变量了。

项目实现

我们知道,Java 中的 int 类型占用 4 个字节(32 位)。在 Java 中,int 类型的取值范围是从 -2,147,483,648 到 2,147,483,647。这个固定的字节大小使得 int 在不同平台上具有一致性。

所以,可以使用位运算将多个 boolean 类型的变量压缩成一个 int 类型的值。

public class BooleanBitPack {
    
    
    private int packedData;

    // 设置第 index 位的值
    public void set(int index, boolean value) {
    
    
        if (value) {
    
    
            packedData |= (1 << index);  // 设置为 1
        } else {
    
    
            packedData &= ~(1 << index); // 设置为 0
        }
    }

    // 获取第 index 位的值
    public boolean get(int index) {
    
    
        return (packedData & (1 << index)) != 0; // 判断该位是否为 1
    }

    // 示例用法
    public static void main(String[] args) {
    
    
        BooleanBitPack packer = new BooleanBitPack();
        
        // 设置 boolean 变量
        packer.set(0, true);  // 第 0 位为 true
        packer.set(1, false); // 第 1 位为 false
        packer.set(2, true);  // 第 2 位为 true
        packer.set(3, true);  // 第 3 位为 true
        
        // 获取 boolean 变量
        System.out.println(packer.get(0)); // true
        System.out.println(packer.get(1)); // false
        System.out.println(packer.get(2)); // true
        System.out.println(packer.get(3)); // true
    }
}

  • packedData 用于存储所有的 boolean 值,每一位代表一个 boolean。
  • set(int index, boolean value) 方法用于设置指定索引的 boolean 值。
  • get(int index) 方法用于获取指定索引的 boolean 值。
位运算的解释

将多个 boolean 值压缩到一个 int 值中的原理主要依赖于 位操作(bit manipulation)。

位的概念

一个 int 类型在 Java(或大多数编程语言)中通常是 32 位的。这意味着它可以表示 2^32 种不同的值。通过使用每一位的 0 和 1,可以有效地存储多种信息。

使用位来表示布尔值

每一位可以表示一个布尔值:
0 表示 false
1 表示 true
因此,一个 int 值可以用来表示最多 32 个布尔值(32 位)。

位操作
  • 按位与(&):可以用来检查某一位是否为 1。
  • 按位或(|):可以用来设置某一位为 1。
  • 按位非(~):可以用来翻转位的值。
  • 左移(<<):可以用来将某一位移动到指定位置,用于设置位的操作。
  • 右移(>>):可以用来获取某一位的值。

举个例子,位移操作:

1 << index:

这是一个左移操作,将数字 1 向左移动 index 位。

例如,如果 index 是 2,1 在二进制中是 0000 0001,左移两位后变为 0000 0100(即十进制的 4)。

结果是一个只有第 index 位为 1,其他位为 0 的整数。

优点
  • 节省空间:通过将多个布尔值存储在一个整数中,可以显著减少内存使用。
  • 高效性:位操作速度快,因为它们直接在底层进行处理。
具体操作
  • 设置布尔值:

要设置第 index 位为 true,可以使用 packedData |= (1 << index),这会把 packedData 的第 index 位设为 1。

要设置为 false,可以使用 packedData &= ~(1 << index),这会把 packedData 的第 index 位设为 0。

  • 获取布尔值:

要获取第 index 位的布尔值,可以使用 (packedData & (1 << index)) != 0,这会检查 packedData 的第 index 位是否为 1。

代码详细解释

  • 设置某一位为 1

packedData |= (1 << index) 的原理:

|= 是按位或操作符。

它的作用是将两个数的对应位进行比较,如果其中至少有一个位为 1,则该位的结果为 1。

  • 举个例子

假设 packedData 当前值为 0000 0000(0),我们希望设置第 2 位(index = 2)为 1。

计算 1 << index:

  • 1 << 2 得到 0000 0100(即 4)。

执行 packedData |= (1 << index):

  • 计算 0000 0000 | 0000 0100:
  • 结果是 0000 0100。
  • 这就把 packedData 的第 2 位设置为 1。

  • 设置某一位为 0

packedData &= ~(1 << index) 的原理:

&= 是按位与操作符。
& 只有在两个数的对应位都是 1 时结果才为 1,否则为 0。

~ 是按位取反操作符,它会把 0 变成 1,把 1 变成 0。

  • 举个例子

假设 packedData 当前值为 0000 0100(4),我们希望将第 2 位(index = 2)设置为 0。

计算 1 << index:

  • 1 << 2 得到 0000 0100(即 4)。

取反 ~(1 << index):

  • ~0000 0100 得到 1111 1011(即 -5,若用补码表示)。

执行 packedData &= ~(1 << index):

  • 计算 0000 0100 & 1111 1011:
  • 结果是 0000 0000。
  • 这就把 packedData 的第 2 位设置为 0。

总结
  • 利用位运算可以高效地操作一个整数中的多个布尔值,每一位代表一个布尔值。
  • |= 操作用于将某一位设置为 1,而 &= 结合取反操作用于将某一位设置为 0。
  • 这种方法节省了内存,允许我们在一个整数中存储多个状态,特别适合需要管理多个开关的场景。

猜你喜欢

转载自blog.csdn.net/qq_43358469/article/details/143484809