2012-05-02 15 views
3

我得到了一個包含n部分消息的映射爲字節數組。在最後一幅作品進入地圖後,必須將該信息連接起來。我發現了兩個應該滿足要求的解決方案。第一個是使用System.arraycopy:儘可能快的字節數組連接方法

public byte[] getMessageBytes() throws IOException { 
    byte[] bytes = new byte[0]; 
    for (final Map.Entry<Short,byte[]> entry : myMap.entrySet()) { 
     byte[] entryBytes = entry.getValue(); 
     byte[] temp = new byte[bytes.length + entryBytes.length]; 
     System.arraycopy(bytes, 0, temp, 0, bytes.length); 
     System.arraycopy(entryBytes, 0, temp, bytes.length, entryBytes.length); 
     bytes = temp; 
    } 
    return bytes; 
} 

而第二個是使用ByteArrayOutputStream:

public byte[] getMessageBytes() throws IOException { 
    final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    for (final Map.Entry<Short,byte[]> entry : myMap.entrySet()) { 
     baos.write(entry.getValue()); 
    } 
    baos.flush(); 
    return baos.toByteArray(); 
} 

什麼是從性能和內存使用的角度看到的更好的方法? 是否有另一種更好的連接方式?

+5

你有沒有對這些進行基準測試,發現它們速度不夠快? – Poindexter

+0

這真的是你的瓶頸嗎? – ControlAltDel

+0

@Poindexter我發現如果地圖中有很多條目,這需要在洞過程中花費一些時間。所以我尋求改進。 – sebastian

回答

8

由於可以通過添加了片的長度找出消息的大小,我將:

  1. 加起來片的長度,並分配輸出陣列;
  2. 使用一個循環到arraycopy()每一塊到輸出數組的正確位置。

這很可能是內存高效且快速的。但是,只有分析才能說出完整的故事。

0

正確的答案是測試和比較您的特定情況。

是一個SortedMap,就像一個TreeMap或者你實際上是隨機合併字節?

+0

這是一個TreeMap。 – sebastian

4

這應該表現得比你的第一個版本(未測試)

public byte[] getMessageBytes() throws IOException { 
    long amount = 0L; 
    long offset = 0L; 
    // no reason to use entrySet() if you just use the values 
    for (byte[] arr : myMap.values()) { 
     amount += arr.length; 
    } 
    byte[] dest = new byte[amount]; 
    for (byte[] arr : myMap.values()) { 
     System.arraycopy(arr, 0, dest, offset, arr.length); 
     offset += arr.length; 
    } 
    return dest; 
} 

(這個答案大致相當於AIX的)

+0

這是否假設您要連接數組的順序是值集的順序?自從我寫了java以來​​已經有一段時間了,但我不認爲有一個值的訂單gaurantee()Set是否存在? – Aidos

+0

@Aidos是真的,但是由於OP使用了這個,我也是這樣做的,雖然順序沒有保證(除非它是一個SortedMap),但我知道的所有地圖實現將在多次調用時以相同順序迭代,除非地圖具有變 –

0

,對於每次迭代創建新的數組你的第一個解決方案是O更好(n^2),這是一個問題,如果你有很多條目。另外它相當複雜。

使用ByteArrayOutputStream更好的原因有兩個:它運行在O(n)中,並且非常簡單。

最有可能快一點的是:如果你首先計算總大小,然後使用System.arraycopy。但我只會這樣做,如果ByteArrayOutputStream是真的太慢。

0

首先計算大小並分配一次結果應該是返回字節數組的最快解決方案。

如果稍後使用得到的字節數組作爲InputStream,並且根據數組的組合大小,最快的方法可能是完全不連接。在這種情況下,您可以創建一個SequenceInputStream包裝幾個ByteArrayInputStreams。未經檢驗的示例代碼:

Collection<byte[]> values = map.values(); 
List<ByteArrayInputStream> streams = new ArrayList<ByteArrayInputStream>(values.size()); 
for (byte[] bytes : values) { 
    streams.add(new ByteArrayInputStream(bytes)); 
} 
return new SequenceInputStream(Collections.enumeration(streams)); 
相關問題