You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中如何将有符号Long转为ByteArray并保持排序顺序?

Kotlin实现Long转保持字典序的ByteArray

需求说明

需要将Kotlin中的有符号Long类型转换为ByteArray,要求生成的字节数组的字典序与原Long值的数值顺序完全一致,且每个Long对应固定的8字节数组。

已尝试ByteBuffer#putLong、DataOutputStream#writeLong及手动小端编码等方案,但均无法满足顺序保持的要求。

参考测试用例

class LongToByteArrayTest {

   @Test
   fun canConvertLongToByteArrayPreservingOrder(){
        // 测试用的Long值集合
        val longs = mutableListOf(
            Long.MIN_VALUE, 
            Long.MAX_VALUE, 
            0, -1, +1, -2, +2, -10, +10, -42, +42, 
            Long.MAX_VALUE / 2, Long.MIN_VALUE / 2
        )
        longs.sort()

        for ((lower, upper) in longs.windowed(size = 2)) {
            println("Lower: ${lower}, Upper: ${upper}")
            assert(lower < upper) { "Fail: long values are out of order!" }

            val lowerBytes = toStableBytes(lower)
            val upperBytes = toStableBytes(upper)

            assert(compareBytesLex(lowerBytes, upperBytes) < 0){ "Fail: byte arrays are out of order!" }
        }
   }


   fun compareBytesLex(byteArray1: ByteArray, byteArray2: ByteArray): Int {
        val min = min(byteArray1.size, byteArray2.size)

        for (i in 0 until min) {
            val myByteUnsigned = byteArray1[i].toInt() and 0xff
            val otherByteUnsigned = byteArray2[i].toInt() and 0xff
            val cmp = myByteUnsigned - otherByteUnsigned
            if (cmp != 0) {
                return cmp
            }
        }

        return byteArray1.size - byteArray2.size
   }

   fun toStableBytes(value: Long) : ByteArray {
       TODO("how do we do this?")
   }

}

解决方案:实现toStableBytes方法

核心思路是调整有符号Long的符号位,将其转换为无符号语义的数值后,再按大端序(高位在前)编码为字节数组。这样处理后,字节数组的字典序会和原Long的数值顺序完全匹配。

具体实现代码:

fun toStableBytes(value: Long): ByteArray {
    // 转换为"无符号化"的Long:翻转符号位,让负数编码整体小于正数
    val adjusted = value xor Long.MIN_VALUE
    return ByteArray(8).apply {
        // 按大端序写入调整后的值
        this[0] = (adjusted shr 56).toByte()
        this[1] = (adjusted shr 48).toByte()
        this[2] = (adjusted shr 40).toByte()
        this[3] = (adjusted shr 32).toByte()
        this[4] = (adjusted shr 24).toByte()
        this[5] = (adjusted shr 16).toByte()
        this[6] = (adjusted shr 8).toByte()
        this[7] = adjusted.toByte()
    }
}

原理说明

  1. 符号位调整:Long.MIN_VALUE的二进制是最高位为1、其余位为0。通过xor操作翻转原Long的最高符号位:
    • 原负数(符号位1)调整后最高位变为0,对应无符号语义下的较小值
    • 原正数(符号位0)调整后最高位变为1,对应无符号语义下的较大值
      调整后的数值无符号顺序,与原Long的有符号数值顺序完全一致。
  2. 大端序编码:按高位到低位的顺序写入字节数组,确保字典序比较时高位字节优先级更高,和数值大小比较逻辑对齐。

验证

将上述实现替换测试用例中的TODO代码后,所有测试用例均可通过,满足字节数组字典序与原Long数值顺序一致的要求。

内容的提问来源于stack exchange,提问作者Martin Häusler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 23:07:44