Schnellstmögliche byte-array-Verkettung-Methode
Bekam ich eine Karte mit n Teile einer Nachricht als byte-array. Nach dem letzten Stück hat seinen Weg gefunden in die Karte, die Meldung verkettet werden. Ich fand zwei Lösungen, die, sollten die Anforderungen erfüllen. Erste ist mit dem 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;
}
Und das zweite ist mit 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();
}
Was ist die bessere Methode, aus der Sicht von performance und Speicherbedarf?
Gibt es eine alternative Art und Weise zu tun, die Verkettung, die noch besser ist?
- Haben Sie zudem diese und fanden Sie nicht schnell genug?
- ist das wirklich dein Flaschenhals?
- Ich fand dies dauert einige Zeit in das Loch Prozess, wenn die Karte hat viele Einträge. So suchte ich nach einer Verbesserung.
- Können Sie einfach entfernen Sie die Karte und verketten von Anfang an?
- Oft ist es besser, diese Dinge zu tun, wie Sie gehen. Können Sie erstellen ein ByteArrayOutputStream statt einer Karte von Anfang an. BTW, eine Kurze und eine Ganzzahl verwendet die gleiche Menge an Speicher.
- Ich hatte schon diese Lösung, aber der Zugriff auf einen ByteArrayOutputStream von mehreren threads synchronisiert und langsam.
- die Anzahl der Einträge sehr hoch sein kann. Wenn ich dies schneller würde es verbessern.
- Mit der Karte gibt mir den Vorteil, das einfügen der Werte parallel von mehreren threads, sonst kann ich hade zu synchronisieren.
- Wenn Sie wissen, die Größe im Voraus können Sie das liest gleichzeitigen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Da können Sie herausfinden, die Größe der Nachricht durch addition der Längen der einzelnen Stücke würde ich:
arraycopy()
jedes Stück in der richtigen position im Ausgabe-array.Dies ist wahrscheinlich der Speicher-effizient und schnell. Allerdings nur profiling kann die ganze Geschichte erzählen.
Diese ausführen sollte, sogar besser als deine erste version (noch nicht getestet)
(Diese Antwort entspricht ungefähr aix)
Die richtige Antwort ist, Tests und vergleichen für Ihre spezielle situation.
Ist, dass eine SortedMap, wie eine TreeMap oder sind Sie tatsächlich die Zusammenlegung der bytes nach dem Zufallsprinzip?
Ihre erste Lösung, wird ein neues array erstellt, die für jede iteration ist O(n^2), das ist ein problem, wenn Sie viele Einträge haben. Plus, es ist ziemlich Komplex.
Mit ByteArrayOutputStream ist besser, aus zwei Gründen: es läuft in O(n), und es ist sehr einfach.
Wahrscheinlich ein wenig schneller ist: wenn du zuerst berechnen Sie die gesamte Größe, und verwenden Sie dann System.arraycopy. Aber ich würde das nur tun, wenn die ByteArrayOutputStream ist wirklich zu langsam.
Berechnung der Größe der ersten und der Zuweisung das Ergebnis einmal sollte die Schnellste Lösung, um wieder eine byte-array.
Wenn Sie das resultierende byte-array als ein
InputStream
später, und abhängig von der Gesamtgröße des arrays, der Schnellste Weg könnte sein, nicht verketten überhaupt. In diesem Fall können Sie erstellen eineSequenceInputStream
Einschlag mehrererByteArrayInputStreams
. Ungetesteten Beispielcode: