如何将UUID的ArrayList转换为ByteArray?

huangapple go评论81阅读模式
英文:

How Do I Convert An ArrayList of UUID To A ByteArray?

问题

object UUIDConversion {
    fun UUID.toByteArray(): ByteArray {
        val byteBuffer = ByteBuffer.wrap(ByteArray(16))
        byteBuffer.putLong(this.mostSignificantBits)
        byteBuffer.putLong(this.leastSignificantBits)
        return byteBuffer.array()
    }

    fun ByteArray.toUUID(): UUID {
        val byteBuffer = ByteBuffer.wrap(this)
        val mostSignificantBits = byteBuffer.long
        val leastSignificantBits = byteBuffer.long
        return UUID(mostSignificantBits, leastSignificantBits)
    }

    fun ArrayList<UUID>.toByteArray(): ByteArray {
        val byteBuffer = ByteBuffer.wrap(ByteArray(size * 16))
        for (uuid in this) {
            byteBuffer.putLong(uuid.mostSignificantBits)
            byteBuffer.putLong(uuid.leastSignificantBits)
        }
        return byteBuffer.array()
    }

    fun ByteArray.toUUIDList(): ArrayList<UUID> {
        val byteBuffer = ByteBuffer.wrap(this)
        val uuidList = ArrayList<UUID>()
        while (byteBuffer.hasRemaining()) {
            val mostSignificantBits = byteBuffer.long
            val leastSignificantBits = byteBuffer.long
            uuidList.add(UUID(mostSignificantBits, leastSignificantBits))
        }
        return uuidList
    }
}

With these additional functions, you can now convert an ArrayList<UUID> to a ByteArray and vice versa using the toByteArray() and toUUIDList() functions.

英文:
object UUIDConversion {
    fun UUID.toByteArray() : ByteArray {
        val byteBuffer = ByteBuffer.wrap(ByteArray(16))
        byteBuffer.putLong(this.mostSignificantBits)
        byteBuffer.putLong(this.leastSignificantBits)
        return byteBuffer.array()
    }
    fun ByteArray.toUUID() : UUID {
        val byteBuffer = ByteBuffer.wrap(this)
        val mostSignificantBits = byteBuffer.long
        val leastSignificantBits = byteBuffer.long
        return UUID(mostSignificantBits, leastSignificantBits)
    }
}

I have the code above to convert a UUID to a ByteArray and convert it back but I also need to be able to convert an ArrayList<UUID> to a ByteArray and convert it back. How would I do that exactly? If you're wondering why I need to do this it's because I need to store a HashMap<UUID, ArrayList<UUID> in a key-value database and I need to convert it to a ByteArray and back to use it.

Java or Kotlin answers are both fine.

答案1

得分: 1

你可以只使用+运算符来连接独立的UUID字节数组,如下所示:

val allUUIDs : ByteArray = listOfUUID.fold(ByteArray(0)) { buffer, uuid -> buffer + uuid.toByteArray() }

然而,如果你有很长的链条要转换,也许性能会显著下降。相反,你可以创建专门的方法来从/写入字节缓冲区:

import java.nio.ByteBuffer
import java.util.*
import kotlin.RuntimeException

fun ByteBuffer.readUUIDs(nbUUIDs : Int = remaining()/16) : Sequence<UUID> {
    if (nbUUIDs <= 0) return emptySequence()
    val nbBytes = nbUUIDs * 16
    // 防御性复制 -> 结果序列与接收缓冲区独立
    val defCpy = ByteArray(nbBytes)
    // 切片(slice)是必需的,以保持源缓冲区不受影响
    slice().get(defCpy)
    val view = ByteBuffer.wrap(defCpy)
    return (1..nbUUIDs).asSequence()
        .map { UUID(view.long, view.long) }
}

fun List<UUID>?.write() : ByteBuffer? {
    if (this == null || isEmpty()) return null;
    val buffer = ByteBuffer.allocate(Math.multiplyExact(size, 16))
    forEach { uuid ->
        buffer.putLong(uuid.mostSignificantBits)
        buffer.putLong(uuid.leastSignificantBits)
    }
    buffer.rewind()
    return buffer
}

fun main() {
    val uuids = (0..3).asSequence().map { UUID.randomUUID() }.toList()
    val writtenUUIDs = uuids.write()
    val uuidSequence = writtenUUIDs ?.readUUIDs() ?: throw RuntimeException("Bug")

    // 请注意,现在我们可以对缓冲区进行任何操作,而不会影响序列
    writtenUUIDs.getLong()
    writtenUUIDs.putLong(-1)

    val readBack = uuidSequence?.toList()
    assert(uuids == readBack) { throw RuntimeException("Bug") }
    println(uuids)
    println(readBack)
}
英文:

You could just use + operator to concatenate independant UUID byte arrays, like so:

val allUUIDs : ByteArray = listOfUUID.fold(ByteArray(0)) { buffer, uuid -&gt; buffer + uuid.toByteArray() }

However, if you have long chains to convert, maybe performance could signicantly drop. Instead, you can make dedicated methods to read/write to/from byte buffers:

import java.nio.ByteBuffer
import java.util.*
import kotlin.RuntimeException

fun ByteBuffer.readUUIDs(nbUUIDs : Int = remaining()/16) : Sequence&lt;UUID&gt; {
    if (nbUUIDs &lt;= 0) return emptySequence()
    val nbBytes = nbUUIDs * 16
    // Defensive copy -&gt; resulting sequence becomes independant from receiver buffer
    val defCpy = ByteArray(nbBytes)
    // slice is required to left source buffer untouched
    slice().get(defCpy)
    val view = ByteBuffer.wrap(defCpy)
    return (1..nbUUIDs).asSequence()
        .map { UUID(view.long, view.long) }
}

fun List&lt;UUID&gt;?.write() : ByteBuffer? {
    if (this == null || isEmpty()) return null;
    val buffer = ByteBuffer.allocate(Math.multiplyExact(size, 16))
    forEach { uuid -&gt;
        buffer.putLong(uuid.mostSignificantBits)
        buffer.putLong(uuid.leastSignificantBits)
    }
    buffer.rewind()
    return buffer
}

fun main() {
    val uuids = (0..3).asSequence().map { UUID.randomUUID() }.toList()
    val writtenUUIDs = uuids.write()
    val uuidSequence = writtenUUIDs ?.readUUIDs() ?: throw RuntimeException(&quot;Bug&quot;)

    // Note that now, we can do whatever we want with the buffer. The sequence is not impacted
    writtenUUIDs.getLong()
    writtenUUIDs.putLong(-1)

    val readBack = uuidSequence?.toList()
    assert(uuids == readBack) { throw RuntimeException(&quot;Bug&quot;) }
    println(uuids)
    println(readBack)
}

huangapple
  • 本文由 发表于 2020年8月6日 14:59:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/63278362.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定