2012-06-25 23 views
10

我想「清理」一個ByteBuffer爲全零字節(全部爲0x00)。我試圖循環遍歷緩衝區中的所有位置,並將它們設置爲0x00,但效率很差。有沒有更好的方法來快速清除ByteBuffer - 與BitSet.clear()相似?在Java中快速擦除(不清除)一個ByteBuffer

請注意,ByteBuffer.clear()在這種情況下對我來說不是一個合適的解決方案 - 我必須擦除緩衝區內的所有數據,而不是隻將指針重置爲開始。

任何提示?

編輯:ByteBuffer用作哈希表的一部分,它維護哈希表條目的引用。每次需要刷新散列表時,我都必須重置散列表條目以便以後使用散列表插入。由於散列表是以隨機方式訪問的,我不能簡單地清除()字節緩衝區的狀態。

+0

您可以更詳細地解釋用例嗎?你從哪裏獲得bytebuffer? – jontro

+0

爲什麼你認爲你需要將緩衝區清零? – EJP

+0

它是直接緩衝區嗎?如果不是,那麼'ByteBuffer.wrap(new byte [123456]);' –

回答

6

您是否嘗試過使用ByteBuffer.put(byte[])ByteBuffer.put(ByteBuffer)方法之一來一次性寫入多個零?然後,您可以使用預先填充零的數組或緩衝區以100或1000字節的塊爲單位遍歷緩衝區。

缺點:這是一個可選的操作,因此並不要求字節緩衝區的所有的實現提供它...

+0

會試試看。希望批量投入會比循環... thx更好! – asksw0rder

+2

對不起,這個遲到的回覆,但這種方法真的可以減少衝洗的開銷。我看到沖洗時間從〜60ms減少到〜2ms。將看看它是否夠好。 – asksw0rder

4

對於ByteBuffer實現,提供了可選array()方法(其中hasArray()回報true),您可以使用此方法獲取對底層數組的引用,然後使用java.util.Arrays#fill()

1

如果在刷新哈希表後需要一個新的乾淨的零填充的ByteBuffer,最簡單的方法是忘記現有的ByteBufefr並分配一個新的。官方文檔沒有這麼說,但所有已知的實現都沒有記錄新的緩衝區。有關其他信息,請參閱http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6535542

1

隨着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(提供Platform.ARCH作爲訪問os.arch系統屬性的方便,規範方法)時,我將如何爲Oracle JRE進行設置。

/** 
* 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");