在 Java 编程中,我们经常需要和二进制打交道 —— 统计二进制中 1 的个数、判断奇偶、权限控制… 而Integer.bitCount()(以及Long.bitCount())就是处理这类问题的 “神兵利器”。本文会用最通俗的语言,从原理到实战,带你彻底搞懂bitCount的所有用法,新手也能轻松上手!

一、先搞懂:bitCount 到底是个啥?

1. 核心定义

bitCount是 JDK 内置的静态方法(Integer/Long类中),作用是统计一个整数的二进制表示中 “1” 的个数(也叫 “汉明重量”)。

举个栗子:

1.数字5的二进制是101 → 有 2 个 1 → Integer.bitCount(5) = 2

2.数字-1(补码全 1)→ Integer.bitCount(-1) = 32(int 占 32 位)

2. 基础用法(一行代码搞定)

public class BitCountDemo {
    public static void main(String[] args) {
        // 正数示例
        int num1 = 7; // 二进制:111
        System.out.println(Integer.bitCount(num1)); // 输出:3
        
        // 负数示例(补码计算)
        int num2 = -2; // 补码:11111111 11111111 11111111 11111110
        System.out.println(Integer.bitCount(num2)); // 输出:31
        
        // 长整数示例
        long num3 = 123456789L;
        System.out.println(Long.bitCount(num3)); // 输出:16
    }
}

3. 为什么不用自己写?

可能有同学会想:“统计 1 的个数我用循环也能写啊?”—— 确实可以,但 JDK 的bitCount是底层优化的位运算实现,比手写循环快 10 倍以上!

// 手写统计1的个数(效率低)
public static int myBitCount(int num) {
    int count = 0;
    while (num != 0) {
        count += num & 1; // 判断最后一位是否为1
        num >>>= 1; // 无符号右移
    }
    return count;
}

而 JDK 的bitCount用了 “分治法”(类似(n & 0x55555555) + ((n >>> 1) & 0x55555555)),直接操作二进制位,效率拉满。

二、bitCount 的 6 个实用场景(附示例)

场景 1:快速判断奇偶?No!是更高级的 “位数判断”

新手常用来判断奇偶(num % 2),但bitCount能做更灵活的判断:

  • 判断是否是 2 的幂:bitCount(num) == 1(2 的幂的二进制只有 1 个 1)
  • 判断是否是奇数个 1:bitCount(num) % 2 == 1
// 判断是否是2的幂(如2、4、8、16…)
public static boolean isPowerOfTwo(int num) {
    return num > 0 && Integer.bitCount(num) == 1;
}

public static void main(String[] args) {
    System.out.println(isPowerOfTwo(8));  // true(1000)
    System.out.println(isPowerOfTwo(9));  // false(1001)
}

场景 2:权限控制(二进制掩码)

在权限设计中,常用 “二进制位” 表示不同权限(比如 0001 = 读、0010 = 写、0100 = 删、1000 = 改),bitCount可以快速统计 “拥有的权限数量”。

// 权限定义
public class Permission {
    public static final int READ = 1;    // 0001
    public static final int WRITE = 2;   // 0010
    public static final int DELETE = 4;  // 0100
    public static final int UPDATE = 8;  // 1000

    // 统计用户拥有的权限数
    public static int countPermission(int userPerm) {
        return Integer.bitCount(userPerm);
    }

    public static void main(String[] args) {
        // 用户拥有:读+写+删(0001+0010+0100=0111)
        int userPerm = READ | WRITE | DELETE;
        System.out.println("拥有的权限数:" + countPermission(userPerm)); // 输出3
    }
}

场景 3:数组去重(位掩码优化)

如果数组元素是 0-31 的整数,可用一个 int 变量做位掩码,bitCount统计去重后的元素个数:

public static int countUnique(int[] arr) {
    int mask = 0;
    for (int num : arr) {
        mask |= (1 << num); // 对应位标记为1
    }
    return Integer.bitCount(mask); // 有多少个1就是多少个唯一元素
}

public static void main(String[] args) {
    int[] arr = {1, 2, 2, 3, 3, 3};
    System.out.println("去重后元素数:" + countUnique(arr)); // 输出3
}

场景 4:计算两个数的 “汉明距离”

汉明距离 = 两个数二进制位不同的个数 → 先异或(不同位为 1),再统计 1 的个数:

// 计算汉明距离
public static int hammingDistance(int a, int b) {
    return Integer.bitCount(a ^ b);
}

public static void main(String[] args) {
    System.out.println(hammingDistance(1, 4)); // 1(001) ^ 4(100) = 5(101) → 输出2
}

场景 5:统计数组中元素的 “1 的总个数”

批量统计多个数字的二进制 1 的总数,比如刷题时的 “数组元素二进制位数总和”:

public static int totalOneBits(int[] arr) {
    int total = 0;
    for (int num : arr) {
        total += Integer.bitCount(num);
    }
    return total;
}

public static void main(String[] args) {
    int[] arr = {1, 2, 3}; // 1(1) + 2(10) + 3(11) → 1+1+2=4
    System.out.println("总1的个数:" + totalOneBits(arr)); // 输出4
}

场景 6:性能优化(替代循环乘法)

之前有同学问过 “重复乘以二进制 1 的个数” 的需求,用bitCount + 快速幂能把 O (n*m) 优化为 O (n):

public static void multiplyByBitCount(int[] arr, int m) {
    for (int i = 0; i < arr.length; i++) {
        int cnt = Integer.bitCount(arr[i]);
        arr[i] = (int) (arr[i] * Math.pow(cnt, m)); // 等价于重复乘m次
    }
}

public static void main(String[] args) {
    int[] arr = {3, 7};
    multiplyByBitCount(arr, 2);
    // 3(11)→cnt=2 → 3*2²=12;7(111)→cnt=3 →7*3²=63
    System.out.println(Arrays.toString(arr)); // 输出[12, 63]
}

三、避坑指南(新手必看)

1. 负数的坑

Integer.bitCount(-1)返回 32,因为 int 是 32 位,负数以补码存储(-1 的补码是全 1)。如果只想统计 “绝对值” 的 1 的个数,先转正数:

int num = -5;
System.out.println(Integer.bitCount(Math.abs(num))); // 5(101) → 输出2

2. 超出范围的坑

Integer.bitCount只能处理 int(32 位),如果是 long 类型,必须用Long.bitCount():

long num = 123456789012345L;
System.out.println(Long.bitCount(num)); // 正确
// System.out.println(Integer.bitCount((int)num)); // 错误,会截断

3. 空值 / 0 的坑

Integer.bitCount(0)返回 0(0 的二进制没有 1),使用前确保参数不为 null(基本类型 int 不会为 null,但包装类 Integer 要注意)

4.用法对比表

用法场景手写实现bitCount 实现效率对比
统计 1 的个数循环 + 位运算Integer.bitCount(num)快 10 倍以上
汉明距离循环对比每一位Integer.bitCount(a^b)代码少 80%
权限数统计循环判断每一位权限Integer.bitCount(perm)逻辑更清晰

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐