Appearance
位运算基础(Java / Android 复习用)
一句话定义
位运算是按二进制每一位做逻辑或移位,用来高效表达标志位、掩码、权限与数值拆合;在 Java 并发与集合底层里很常见,但本身不专属于 HashMap。
可运行 Demo:bitwise-operators-demo · BitwiseOperatorsBasicsDemo.java
为什么要学
| 优势 | 说明 |
|---|---|
| 快 | 常数时间、无分支,CPU 直接做位操作 |
| 省内存 | 一个 int 可塞 32 个布尔标志 |
| 表达力强 | 掩码、权限、协议字段、hash 拌位都靠它 |
| 劣势 | 说明 |
|---|---|
| 可读性差 | flags & MASK 不如命名良好的 API 直观 |
| 易写错 | 优先级、符号位、>> vs >>> 搞混就翻车 |
| 调试难 | 要会看二进制/十六进制才舒服 |
符号速查
| 符号 | 名称 | 规则(两位) | 常见用途 |
|---|---|---|---|
& | 按位与 | 都是 1 才 1 | 掩码:取出或清零某些位 |
| | 按位或 | 有 1 就 1 | 置位:打开某些标志 |
^ | 按位异或 | 相同 0,不同 1 | 切换位、简单混淆、拌散数据 |
~ | 按位非 | 0↔1 | 配合掩码做「取反后清零」 |
<< | 左移 | 右补 0 | x << n ≈ x × 2^n |
>> | 有符号右移 | 负数左补 1 | 带符号整数除 2(向负无穷取整) |
>>> | 无符号右移 | 左补 0 | 把高位「挪」到低段;无符号语义 |
& 按位与 — 掩码筛子
比喻:一串 32 个开关,掩码 mask 标出「我只关心这几格」,value & mask 把其它位清零。
java
int READ = 1 << 0; // 0001
int WRITE = 1 << 1; // 0010
int flags = READ | WRITE;
boolean canRead = (flags & READ) != 0;
int lowNibble = value & 0x0F; // 只保留低 4 位优劣:判标志、取字段极快;但 if ((flags & X) != 0) 不如枚举类型安全。
| 与 ^
java
flags |= READ; // 打开 READ 位
flags ^= TOGGLE_BIT; // 翻转某一位^ 性质: a ^ a = 0,a ^ 0 = a — 有时用于无临时变量交换(面试题,工程少用)。
移位:<< / >> / >>>
| 表达式 | 直观 |
|---|---|
1 << 3 | 8(第 3 位为 1) |
x << 2 | x 乘 4(溢出则截断) |
-1 >> 1 | 仍是 -1(符号位填充) |
-1 >>> 1 | 大正数(左边补 0) |
何时用 >>>:需要把高位无符号地参与低位计算时用 >>>;带符号除法用 >>。
Android / Java 工程常见用途
| 场景 | 典型写法 |
|---|---|
View 可见性、协议 flag | flags & MASK |
| 权限位、能力位 | |= 置位,&= ~MASK 清位 |
| 颜色 ARGB | (alpha << 24) | (red << 16) | ... |
| 取低几位下标 / 对齐 | index & (size - 1)(size 为 2 的幂时) |
| hash 拌位(集合专题) | h ^ (h >>> 16) — 详见 map-concurrency-compare |
和后续专题的关系
- HashMap 下标、扩容 rehash → 留在 map-concurrency-compare,不在本文展开。
- CAS / Atomic* → CAS 与无锁原子基础
复习检查题
&和&&有什么区别?答:
&是按位与(对int/long等逐位运算);用在boolean上时是逻辑与,但两侧都会求值,不短路。&&只能用于boolean,是逻辑与且短路:左为false时不再算右侧。整数之间不能用&&;判标志位用(flags & READ) != 0,不是flags && READ。-1 >> 4和-1 >>> 4为何不同?答:
int的-1二进制为 32 个1。>>有符号右移,高位补符号位1,结果仍是-1。>>>无符号右移,高位补0,低 28 位为1,结果是268435455(0x0FFFFFFF)。集合 hash 拌位用>>>,就是要避免符号位干扰低位。如何用位运算判断
flags是否包含READ?答:
READ为单 bit 时常写(flags & READ) != 0。若READ可能多位组合,用(flags & READ) == READ表示「这些位都已打开」。打开/关闭分别用flags |= READ、flags &= ~READ。为什么说「掩码取低 n 位」要求模数是 2 的幂?
答:当
size = 2^n时,size - 1的二进制是低 n 位全 1,index & (size - 1)等价于index % size,且比取模更快。若size不是 2 的幂,(size - 1)不再是连续低位掩码,按位与的结果不等于取模,下标会算错(HashMap 因此要求容量为 2 的幂)。
速记
&筛位,|开位,^翻位,~取反。<</>>乘除 2 的幂;无符号语义用>>>。- 位运算快但难读;标志位、掩码、颜色、协议最常见。