Long.rotateLeft()Long.rotateRight()java.lang.Long 类中提供的位旋转(Bit Rotation)操作方法,用于对 64 位 long 值的二进制位进行循环左移循环右移。它们在加密算法、哈希函数、随机数生成等底层算法中非常有用。


📚 一、方法定义

1. Long.rotateLeft(long i, int distance)

public static long rotateLeft(long i, int distance)
  • 功能:将 longi 的二进制位向左循环移动 distance 位。
  • 返回值:旋转后的 long 值。

2. Long.rotateRight(long i, int distance)

public static long rotateRight(long i, int distance)
  • 功能:将 longi 的二进制位向右循环移动 distance 位。
  • 返回值:旋转后的 long 值。

⚠️ 注意:这两个方法返回的是 long 基本类型,不是 Long 对象。


🔍 二、核心概念:什么是“位旋转”?

与普通的“逻辑/算术移位”不同,位旋转(也称循环移位)的特点是:

  • 被移出的一端的位会从另一端重新插入,不会丢失。
  • 所有 64 个位整体像一个“环”一样循环移动。

🔄 对比:移位 vs 旋转

操作 示例(8位简化)
<< 2(左移) 10110100 << 2 → 11010000(左边丢弃,右边补0)
rotateLeft(2) 10110100 → 11010010(左边移出的 10 从右边补回)

💡 三、工作原理与计算方式

✅ 1. rotateLeft(i, distance)

等价于:

(i << distance) | (i >>> (-distance & 63))

或更直观理解:

  • 左移 distance
  • 将左移时“溢出”的高位,通过无符号右移补到低位

✅ 2. rotateRight(i, distance)

等价于:

(i >>> distance) | (i << (-distance & 63))
  • 右移 distance
  • 将右移时“溢出”的低位,通过左移补到高位

🔢 为什么是 & 63
因为 long 是 64 位,distance & 63 相当于 distance % 64,确保位移量在 0~63 范围内,避免无效移位。


🧪 四、示例代码

示例 1:基本使用

public class LongRotateExample {
    public static void main(String[] args) {
        long value = 0x123456789ABCDEF0L; // 64位十六进制数
        System.out.printf("原始值: %16s%n", Long.toBinaryString(value));

        // 循环左移 4 位
        long left = Long.rotateLeft(value, 4);
        System.out.printf("左旋 4: %16s%n", Long.toBinaryString(left));

        // 循环右移 4 位
        long right = Long.rotateRight(value, 4);
        System.out.printf("右旋 4: %16s%n", Long.toBinaryString(right));

        // 验证:左旋4 + 右旋4 应该回到原值
        long roundTrip = Long.rotateRight(Long.rotateLeft(value, 4), 4);
        System.out.println("往返验证: " + (value == roundTrip)); // true
    }
}

示例 2:小数值演示(便于观察)

// 以 8 位为例(实际是 64 位)
long x = 0b11001010L; // 二进制表示
System.out.println("原始: " + Long.toBinaryString(x)); // 11001010

long left1 = Long.rotateLeft(x, 2);
System.out.println("左旋2: " + Long.toBinaryString(left1)); 
// 00101011 → 左边的 '11' 移到右边

long right1 = Long.rotateRight(x, 2);
System.out.println("右旋2: " + Long.toBinaryString(right1));
// 10110010 → 右边的 '10' 移到左边

示例 3:位移量大于 64 的情况

long val = 0b1010L;
// rotateLeft(66) 等价于 rotateLeft(66 % 64 = 2)
long result = Long.rotateLeft(val, 66);
// 实际左移 2 位

🛠️ 五、使用技巧

技巧 说明
✅ 用于实现哈希函数 如 MurmurHash、xxHash 中广泛使用位旋转
✅ 提高位混淆性 旋转比普通移位更能打乱位分布,增强随机性
✅ 避免信息丢失 <</>> 不同,旋转不会丢失任何位
✅ 可组合使用 rotateLeft(a, 13) ^ rotateLeft(a, 23) 是常见混淆操作
✅ 替代手动位操作 比手动写 (i << n) | (i >>> (64-n)) 更简洁安全

⚠️ 六、注意事项

  1. 位移量自动取模

    • distance 会被自动对 64 取模(通过 & 63),所以 rotateLeft(x, 70) 等价于 rotateLeft(x, 6)
  2. 无符号右移 >>>

    • 内部使用 >>> 而非 >>,确保高位补 0,避免符号位影响。
  3. 性能极高

    • 这些方法通常被 JVM 优化为单条 CPU 指令(如 x86 的 rol/ror),性能极佳。
  4. 不可变性

    • 原始值不变,返回新值。

❌ 七、常见错误

错误 正确做法
误以为是普通移位 明确区分 <<rotateLeft()
期望返回 Long 对象 返回的是 long 基本类型
忽视负数位移量 负的 distance 也会被处理(如 rotateLeft(x, -4) 等价于 rotateRight(x, 4)
手动实现错误 忘记使用 >>> 或未处理 64-n 边界

🏆 八、最佳实践与性能优化

场景 推荐
✅ 哈希/加密算法 使用 rotateLeft/Right 增强混淆
✅ 随机数生成 用于状态混淆(如 SplitMix64)
✅ 高性能位操作 替代复杂位运算组合
❌ 普通业务逻辑 除非必要,避免使用(可读性较低)

示例:模拟 SplitMix64 的部分操作

long z = seed + 0x9E3779B97F4A7C15L;
z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L;
z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL;
return Long.rotateLeft(z, 31); // 最终混淆

📊 九、性能对比(与手动实现)

方法 性能 可读性 推荐度
Long.rotateLeft(x, n) ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ✅ 推荐
(x << n) | (x >>> (64-n)) ⭐⭐⭐⭐ ⭐⭐ 一般
查表法 ⭐⭐ ⭐⭐⭐⭐ 仅特殊场景

Long.rotateLeft/Right 是 JVM 内置优化方法,性能最优。


📝 十、总结

项目 内容
核心功能 long 值进行循环左移/右移
关键优势 无位丢失、高性能、CPU 指令级优化
典型应用 哈希函数、加密算法、随机数生成
注意事项 返回 long 而非 Long,位移量自动取模 64
与移位区别 旋转是“环形”移动,移位是“线性”移动
性能 极高,通常编译为单条 CPU 指令
推荐使用 ✅ 在需要位混淆或循环移位时首选

一句话掌握

Long.rotateLeft(x, n)Long.rotateRight(x, n) 实现 64 位值的循环移位,比手动位运算更安全高效,是高性能算法的基石操作。