2012-05-02 10 views
3

メッセージのn個の部分を含むマップをバイト配列として取得しました。最後の部分がマップに入った後、メッセージを連結する必要があります。要件を満たす必要がある2つのソリューションが見つかりました。まず一つは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

正解は、特定の状況をテストして比較することです。

TreeMapのようなSortedMapですか、実際にはランダムにマージしていますか?

+0

これはツリーマップです。 – sebastian

4

これは、各反復のための新しい配列を作成し、あなたの最初のソリューションは、Oである、あなたの最初のバージョン(テストしていない)

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があるとは思わないセットはありますか? – Aidos

+0

@Aidos trueですが、OPがそれを使用していたので、Iもそうでしたし、順序が保証されていない間も(ソートマップでない限り)、私が知っているすべてのマップ実装は、かわった –

0

よりも優れを実行する必要があります(n^2)、多くのエントリがある場合は問題です。プラスそれはかなり複雑です。

ByteArrayOutputStreamの使用は、O(n)で実行される2つの理由により優れています。非常に簡単です。

おそらく少し速いです:最初に合計サイズを計算してから、System.arraycopyを使用します。しかし、私は、ByteArrayOutputStreamがの場合、実際にはが遅すぎる場合にのみそれを行います。

0

最初にサイズを計算し、結果を1回割り当てることは、バイト配列を返す最速の解決策になるはずです。

結果のバイト配列を後でInputStreamとして使用し、配列の合計サイズに応じて、最速の方法はまったく連結しないことがあります。その場合、ByteArrayInputStreamsをラップするSequenceInputStreamを作成することができます。テストされていないサンプルコード:

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)); 
関連する問題