Kennt jemand eine java.util.Map-Implementierung, die für wenig Arbeitsspeicher optimiert ist?

8

Ich habe an den üblichen Orten gesucht (Apache Commons, Google) und konnte keinen finden ...

Es sollte opensource sein.

Sucht ziemlich genau nach einem, der auf einer verknüpften Liste basiert. Der Anwendungsfall ist 10'000 Karten, mit nicht unbedingt vielen Werten. Es muss nicht vergrößert werden, da ich es konvertieren kann, wenn es zu groß wird.

Einige Zahlen, Größen, die einige berechnete jvm-Werte verwenden (8bytes / java.lang.Object, 4bytes / ref), die HashMap ist ungefähr 100 + 32n Bytes, das theoretische Beste ist 12 + 20 * n. & lt; - Ich will das, für kleine n.

    
mike g 11.03.2009, 04:13
quelle

10 Antworten

3

Ok, habe es am Ende selbst implementiert. Ich habe einen Geschwindigkeitsvergleich durchgeführt und festgestellt, dass es im Vergleich zu einer HashMap mit 4 Einträgen immer noch etwas schneller war, aber mit 5 oder mehr langsamer. Ich habe die Tests mit einer langen Liste von Schlüsseln durchgeführt, die ich ähnlich wie eine Liste zufälliger englischer Wörter schreiben wollte.

%Vor%     
mike g 11.03.2009, 19:10
quelle
3

Könnten Sie sich commons-collections ansehen Flat3Map , es ist optimiert, um 3 Werte in 3 Feldern zu speichern und überläuft bei 4 eine andere Karte.

Ich habe die Implementierung nicht betrachtet, aber es lohnt sich, darüber nachzudenken. Das einzige Problem ist, dass seit commons-collections 1.3-kompatibel sind, gibt es keine generischen.

    
Gareth Davis 11.03.2009 07:00
quelle
3

Wickeln Sie eine ArrayList mit der Map-Schnittstelle. Die ArrayList verwendet selbst nur wenige Bytes. Jeder Knoten benötigt zwei Zeiger, einen für den Schlüssel und einen für den Wert. Verwenden Sie die sequenzielle Suche, um nach Werten zu suchen. Solange nur wenige Einträge vorhanden sind, ist die Leistung in Ordnung [*]. Dies wird Ihnen den Spielraum geben, echte Karten für die wenigen Vasen zu verwenden, in denen Sie eine große Anzahl von Werten haben.

*: Nehmen wir an, Ihre durchschnittliche Kartengröße beträgt 10. Heutige Computer können ungefähr 100 Millionen Schlüssel pro Sekunde vergleichen, so dass jede Suche durchschnittlich weniger als fünf Mikrosekunden dauert.

Wenn die Leistung für Ihren Anwendungsfall immer noch zu schlecht ist, können Sie versuchen, das Array nach Schlüssel zu sortieren und die binäre Suche zu verwenden.

    
Aaron Digulla 11.03.2009 09:16
quelle
1

Ich empfehle Ihnen, entweder HashMap, Hashtable oder ConcurrentHashMap von JDK zu verwenden, abhängig von Synchronisations- oder Parallelitätsanforderungen. Wenn Sie sich dafür entscheiden, sie zu verwenden, können Sie initialCapacity und loadFactor im Konstruktor entsprechend anpassen.

Google Sammlungen und Apache Commons Sammlungen bieten mehr Funktionen: LRUMap, ReferenceMap, MultikeyMap und so weiter. Aber ich glaube nicht, dass es nicht nur eine kleine Größe gibt.

    
grayger 11.03.2009 04:45
quelle
1

LinkedHashMap verwendet eine verkettete Liste, denke ich, aber ich bezweifle, dass es für wenig Speicher optimiert ist. In der Regel besteht der ganze Sinn einer Karte darin, Suchvorgänge von Schlüssel zu Wert zu beschleunigen, was erklärt, warum Sie nicht das finden, was Sie in den üblichen Bereichen benötigen. Es könnte einfach am einfachsten sein, eine eigene Implementierung von Map zu schreiben, und vielleicht könntest du sogar den Code freigeben, falls jemand das gleiche braucht.

    
David Z 11.03.2009 05:40
quelle
1

Schreiben Sie den Code in einer Weise, die die Verwendung von Karten verbirgt (Sie sollten das sowieso tun, und es klingt wie Sie auch sind). An dem Punkt, an dem es darauf ankommt, weil Sie den Code profiliert haben und sehen können, dass der Speicher wirklich ein Problem ist, finden Sie einen: -)

Wenn Sie zu diesem Zeitpunkt wissen, dass es ein Problem gibt, dann entschuldige ich mich nicht. Aber zu oft beschäftigen sich die Leute mit der "Idee", dass der Code langsam sein wird / viel Speicher / etc ... und beginnen, ihn zu optimieren, anstatt den Code richtig zu machen.

Wenn Sie also etwas schreiben, von dem Sie wissen, dass es wichtig ist, sollten Sie messen, wie Sie gehen. Zum Beispiel arbeite ich an Code, um Klassendateien zu analysieren, ich mache eine kleine Änderung und sehe dann, wie es die Leistung beeinflusst. Zum Beispiel wusste ich für eine Tatsache, dass eine Änderung, die ich machte (3 Zeilen), mein Programm 4 mal langsamer machte ... Ich verbrachte die Zeit an diesem Punkt, um den schnelleren Weg herauszufinden, es zu tun.

Sind Sie auch sicher, dass Karten benötigt werden, wenn der Wert von "n" klein ist? Vielleicht ist eine Liste schnell genug? Haben Sie auch versucht, die vorhandene Map so zu optimieren, dass sie weniger Speicher benötigt?

    
TofuBeer 11.03.2009 06:31
quelle
0

Vielleicht ist diese Antwort ein bisschen spät, aber werfen Sie einen Blick auf Javolution Projekt. Es enthält Implementierungen vieler Datenstrukturen, die für eingebettete und Echtzeitumgebungen gedacht sind. Konkret gibt es eine FastMap Klasse, die vielleicht genau das macht, was Sie wollen.

    
javashlook 11.03.2009 19:52
quelle
0

Wenn Sie nur String s speichern, sehen Sie sich Ссылка

an

Bearbeiten Oh, Entschuldigung, ich sehe, du suchst nach kleinen, nicht großen Karten, vergiss meinen Rat dann.

    
akuhn 12.03.2009 00:52
quelle
0

Es hängt viel davon ab, wie Sie diese Karten verwenden werden, können Sie sie in einer Aufnahme auffüllen und dann nur nachschauen (brauchen Sie diese Suchfunktionen, um schnell zu sein)?

Eine Implementierung mit einer minimalen Menge an Speicher wäre, alle Elemente in ein Array zu setzen und einen Scan durchzuführen, um Elemente zu finden (aber ich denke, das ist nicht schnell genug für Ihre Bedürfnisse). .

Wenn Sie alle Elemente am Anfang kennen, können Sie versuchen, eine gute Hash-Methode ohne zu viele Kollisionen auszuwählen.

Oder vielleicht könnten Sie TreeMap verwenden, wenn Sie eine langsame Einfügezeit zulassen ...

    
pgras 11.03.2009 09:59
quelle
0

Ich weiß, dass es eine alte Frage ist, aber vielleicht könnte jemand weitere Ideen hinzufügen.

Hinweis: Folgendes wäre nur für eine bestimmte Teilmenge von Anwendungsfällen sinnvoll:

Wenn die Anforderung sehr überlappende Sätze von Schlüsseln enthält (im Extremfall die gleichen Schlüssel für alle Karten), dann könnte eine sehr effektive Lösung sein, "externalise" "Die Schlüssel in Bezug auf Karten und haben die Karten enthalten nur Werte, in einem Array.

Die Implementierung sollte nicht "strukturell" vom Überlappungsfaktor abhängen, aber meine Leistung ist umso besser, je mehr sich die Schlüssel überschneiden. Wie Sie es erwarten würden.

Ich kann keine genauen Details meiner Implementierung angeben, aber es ist wichtig, einen geeigneten Mechanismus zu haben, um Schlüssel (außerhalb des Map-Objekts gespeichert) in Indizes in das Werte-Array zu übersetzen, während das Werte-Array bleiben kann compact , dh haben Sie die Länge fünf, wenn Ihre Map fünf Mappings enthält.

Sagen Sie, die Schlüssel für alle diese Karten befinden sich in einer separaten Karte, die Zahlen zugeordnet ist. Dann geht es darum, die Zahlen und Array-Indizes in Beziehung zu setzen.

Tut mir leid, wenn das nicht spezifisch genug ist, aber ich dachte, die Idee wäre gleichzeitig interessant und einfach und könnte als eine alternative Richtung bei der Entwicklung einer speichereffizienten Map verwendet werden.

Auch hier ist es in hohem Maße für Anwendungsfälle mit hoher "Schlüsselüberlappung" geeignet, ist aber selbst generisch. Kann Leistungsprobleme auftreten, wenn die Überlappung zu niedrig ist, abhängig von den Implementierungsdetails.

    
almondandapricot 01.07.2014 18:59
quelle

Tags und Links