我想“清理”一个 ByteBuffer
全部为零字节(全部 0x00
)。我试图遍历缓冲区中的所有位置并将它们设置为 0x00
但效率很差。有没有更好的方法来快速清除 ByteBuffer
- 类似于什么 BitSet.clear()
呢?
请注意 ByteBuffer.clear()
在这种情况下,对我来说不是一个合适的解决方案 - 我必须擦除缓冲区内的所有数据,而不是仅仅将指针重置为开头。
任何提示?
编辑:ByteBuffer用作哈希表的一部分,它维护哈希表条目的引用。每次需要刷新哈希表时,我都必须重置哈希表条目以便以后的哈希表插入。由于以随机方式访问哈希表,我不能简单地清除()字节缓冲区的状态。
你有没有尝试过使用其中一个 ByteBuffer.put(byte[])
要么 ByteBuffer.put(ByteBuffer)
一次写多个零的方法?然后,您可以使用预填充零的数组或缓冲区,以100或1000字节或其他任何方式迭代缓冲区。
缺点:这是一个可选操作,因此并非所有ByteBuffer实现都需要提供它...
对于 ByteBuffer
提供可选的实现 array()
方法(其中 hasArray()
回报 true
),你可以使用这个方法获取对底层数组的引用,然后使用 java.util.Arrays#fill()
。
如果在刷新哈希表后需要一个新的干净的零填充ByteBuffer,最简单的方法是忘记现有的ByteBufefr并分配一个新的。官方文档没有这么说,但是所有已知的实现都将新缓冲区的内存归零。看到 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6535542 了解更多信息。
正如DNA提到的那样,有一个预先填充的缓冲液并使用 ByteBuffer.put(ByteBuffer)
可能是最快的便携式方式。如果那不实用,你可以做这样的事情来利用其中任何一个 Arrays.fill
要么 Unsafe.putLong
当适用:
public static void fill(ByteBuffer buf, byte b) {
if (buf.hasArray()) {
final int offset = buf.arrayOffset();
Arrays.fill(buf.array(), offset + buf.position(), offset + buf.limit(), b);
buf.position(buf.limit());
} else {
int remaining = buf.remaining();
if (UNALIGNED_ACCESS) {
final int i = (b << 24) | (b << 16) | (b << 8) | b;
final long l = ((long) i << 32) | i;
while (remaining >= 8) {
buf.putLong(l);
remaining -= 8;
}
}
while (remaining-- > 0) {
buf.put(b);
}
}
}
设置 UNALIGNED_ACCESS
需要一些关于JRE实现和平台的知识。以下是我在使用JNA(它提供的)时为Oracle JRE设置它的方法 Platform.ARCH
作为一种方便,规范的方式来访问 os.arch
系统属性)。
/**
* Indicates whether the ByteBuffer implementation likely supports unaligned
* access of multi-byte values on the current platform.
*/
private static final boolean UNALIGNED_ACCESS = Platform.ARCH.startsWith("x86");