在Java中快速擦除(不清楚)ByteBuffer

时间:2012-06-25 21:51:08

标签: java bytebuffer erase

我正在尝试“清理”ByteBuffer为全零字节(全部为0x00)。我试图遍历缓冲区中的所有位置并将它们设置为0x00,但效率很差。有没有更好的方法可以快速清除ByteBuffer - 与BitSet.clear()类似?

请注意,ByteBuffer.clear()在这种情况下对我来说不是一个合适的解决方案 - 我必须清除缓冲区内的所有数据,而不只是将指针重置为开头。

任何提示?

编辑:ByteBuffer用作哈希表的一部分,它维护哈希表条目的引用。每次需要刷新哈希表时,我都必须重置哈希表条目以便以后的哈希表插入。由于哈希表是以随机方式访问的,所以我不能简单地清除()字节缓冲区的状态。

4 个答案:

答案 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.fillUnsafe.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