Java 中 bitCount 的花式用法:从原理到实战,一篇吃透
在 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) | 逻辑更清晰 |
更多推荐


所有评论(0)