位运算改大小写更快,因ascii中大小写字母差值恒为32(即1

为什么用位运算改大小写比调用 toLowerCase() 更快
因为 ASCII 码里,大写字母 A–Z 是连续的 65–90,小写字母 a–z 是 97–122,二者差值恒为 32,而 32 正好是 1 (即二进制第 6 位为 1)。大写转小写只需把第 6 位设为 1,用按位或 <code>| 即可——CPU 一条指令搞定,不查表、不分支、不新建字符串。
但注意:这仅对纯 ASCII 字母有效,ü、α、中 这类字符完全不适用;Java 的 char 是 UTF-16 code unit,遇到代理对(surrogate pair)会直接出错。
怎么用 | 和 32 安全转换单个 char
不能无脑 c | 32,否则像 '0'(ASCII 48)、'@'(64)也会被“误转”。必须先判断是否为大写字母。
- 检查范围:
c >= 'A' && c - 只对满足条件的字符执行:
c | 32 - 其他字符原样返回,包括小写字母、数字、符号、Unicode 字符
示例:
立即学习“Java免费学习笔记(深入)”;
char toLower(char c) {
return (c >= 'A' && c <= 'Z') ? (c | 32) : c;
}
处理字符串时别直接操作 char[] 就完事
Java 字符串不可变,你得自己建新数组;更关键的是:不能假设每个 char 对应一个 Unicode 字符。比如 emoji "??" 在 Java 中占两个 char(代理对),直接遍历 char[] 会把高代理和低代理都“转小写”,结果变成非法码点。
- 如果确定输入只有 ASCII(如 HTTP header、base64 token),可用
String.toCharArray()+ 循环toLower() - 如果可能含非 ASCII,必须用
String.codePoints()流式处理,再用Character.toLowerCase(int cp)——这时位运算就退场了 - 性能敏感且限定 ASCII 场景下,用
ByteBuffer或Unsafe直接操作字节数组更快,但风险陡增
| 32 不等于 += 32,也别用 ^ 32
有人试过 c += 32,看似等价,但隐式类型提升会让 char 变成 int,再赋值回 char 时可能截断;^ 32 是异或,虽然对 A–Z 也能得到小写(因为那一位原本是 0),但一旦输入是 'a'(97,二进制末六位是 100001),^ 32 会把它变回大写,双向污染。
- 坚持用
| 32:确保只开一位,不影响其他位 - 永远加范围检查,不省这两次比较
- 别在循环里重复写
(c >= 'A' && c ,抽成方法或静态常量表达式更清晰
真正难的不是位运算本身,是搞清你的数据边界在哪——ASCII?Latin-1?还是整个 Unicode?选错前提,再快的位操作也只是精准地跑偏。










