我正在尝试“清理”ByteBuffer
为全零字节(全部为0x00
)。我试图遍历缓冲区中的所有位置并将它们设置为0x00
,但效率很差。有没有更好的方法可以快速清除ByteBuffer
- 与BitSet.clear()
类似?
请注意,ByteBuffer.clear()
在这种情况下对我来说不是一个合适的解决方案 - 我必须清除缓冲区内的所有数据,而不只是将指针重置为开头。
任何提示?
编辑:ByteBuffer用作哈希表的一部分,它维护哈希表条目的引用。每次需要刷新哈希表时,我都必须重置哈希表条目以便以后的哈希表插入。由于哈希表是以随机方式访问的,所以我不能简单地清除()字节缓冲区的状态。
答案 0 :(得分:7)
您是否尝试过使用其中一种ByteBuffer.put(byte[])
或ByteBuffer.put(ByteBuffer)
方法一次写入多个零?然后,您可以使用预填充零的数组或缓冲区,以100或1000字节或其他任何方式迭代缓冲区。
下行:这是一个可选操作,因此并非所有ByteBuffer实现都需要提供它...
答案 1 :(得分:4)
对于提供可选ByteBuffer
方法的array()
实现(其中hasArray()
返回true
),您可以使用此方法获取对底层数组的引用,然后使用java.util.Arrays#fill()
。
答案 2 :(得分:2)
正如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");
答案 3 :(得分:1)
如果在刷新哈希表后需要一个全新的零填充ByteBuffer
,最简单的方法是删除现有的ByteBuffer
并分配一个新的。官方文档没有这么说,但是所有已知的实现都将新缓冲区的内存归零。有关其他信息,请参阅http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6535542。