BitSet.xor() 是计算权限位集合对称差集最直接高效的方式,原地修改调用方 BitSet,保留仅存在于其中一个集合的位;执行按位异或,结果位为 true 当且仅当两操作数对应位值不同;适用于权限比对、变更检测等场景,需注意 clone() 避免副作用,并确保权限 ID 为非负整数。

在 Java 中,BitSet.xor() 是计算两个权限位集合对称差集(即“异或”)最直接高效的方式。它会原地修改调用方 BitSet,保留仅存在于其中一个集合、但不同时存在于两个集合中的位 —— 这正是差异权限的精确语义:A 有而 B 没有,或 B 有而 A 没有。
理解 xor() 的行为与权限建模前提
BitSet.xor(BitSet set) 执行的是按位异或(^):结果中某一位为 true 当且仅当两个操作数在该位上值不同。因此:
- 若权限用唯一整数 ID 映射到位索引(如权限 ID=0 → bit 0,ID=5 → bit 5),则
bsA.xor(bsB)后,所有true位对应的就是 A 和 B 的差异权限 ID; - 该操作是可逆且无副作用的(只要保留原始副本),适合用于权限比对、变更检测、最小化授权更新等场景;
- 注意:
xor()会修改调用方,如需保留原 BitSet,应先clone()或使用new BitSet().or(...).xor(...)构造新实例。
快速提取差异权限 ID 列表
执行 xor 后,遍历所有置位(nextSetBit(0))即可获得差异权限的整数 ID:
BitSet diff = (BitSet) bsA.clone(); // 避免修改原 bsA
diff.xor(bsB);
List<Integer> deltaPermissions = new ArrayList<>();
for (int i = diff.nextSetBit(0); i >= 0; i = diff.nextSetBit(i + 1)) {
deltaPermissions.add(i); // i 即权限 ID(假设 ID 与 bit 索引一一对应)
}
此方式时间复杂度为 O(m),m 是差异位数量,远优于遍历全部可能权限空间。
立即学习“Java免费学习笔记(深入)”;
区分“新增”与“撤销”权限(可选增强)
若还需知道哪些是用户新增权限、哪些是被收回权限,可分别计算:
-
新增权限(B 有但 A 没有):
BitSet added = (BitSet) bsB.clone(); added.andNot(bsA); -
撤销权限(A 有但 B 没有):
BitSet revoked = (BitSet) bsA.clone(); revoked.andNot(bsB);
这两个操作配合 xor() 可完整描述权限变更语义,适用于审计日志、增量同步或 UI 权限变更高亮。
实际使用注意事项
务必确保权限 ID 是非负整数且不越界 —— BitSet 不支持负索引,超出当前容量的位会被自动扩容,但频繁扩容影响性能;建议预估最大权限 ID 并用 BitSet(int size) 初始化。另外,BitSet 不是线程安全的,多线程读写需外部同步。


















