Gibt es einen Weg, wie man den Schlüssel (oder den ganzen Eintrag) von einer 'Map' bekommt?

8

Gibt es eine Möglichkeit, wie man den Schlüssel (oder den gesamten Eintrag) von einem HashMap (oder einem anderen geeigneten Map ) effizient bekommt?

Bevor jemand sagt, ich brauche es nie: Ich tue es. Ich habe eine Schleife wie diese

%Vor%

und mein key nimmt unnötig Speicher, der gespeichert werden könnte, wenn ich list.add(key) durch etwas wie list.add(map.getKey(key)) ersetzen könnte (die neue Instanz wäre für GC geeignet). Während sie identisch sind, würde durch die Wiederverwendung der alten Instanz Speicherplatz gespart.

Ich weiß, ich kann den Schlüssel in den Wert einbetten oder Guavas Interner ; beides hilft, aber beides kostet auch etwas Gedächtnis.

Um einige Missverständnisse zu beantworten: Wenn Effizienz kein Problem wäre, würde das folgende tun

%Vor%

Die effizienteste Lösung, wie in der akzeptierten Antwort beschrieben:

%Vor%

Das Problem ist, dass es in package java.util eingefügt werden muss, da es eine private Methode des Pakets verwendet. Es kann gefährlich sein, solch eine Methode zu verwenden, aber es ist kein Problem in meinem "run-once" Anwendungsfall.

    
maaartinus 07.10.2012, 14:18
quelle

8 Antworten

7

Wie viel Böses sind Sie bereit zu begehen, um dies zu tun?

Mit der Schnittstelle Map können Sie weder einen Schlüssel noch einen Eintrag abrufen. Auch nicht die Set -Schnittstelle. Auch nicht die öffentliche Schnittstelle von HashMap .

Aber die HashMap 's Paket Schnittstelle funktioniert (zumindest im Sun JDK). Sehen Sie sich den Quellcode ; In Zeile 355 gibt es eine Methode namens getEntry , die folgendermaßen beginnt:

%Vor%

Ich glaube, das ist genau das, was Sie brauchen. Sie können dies mit Reflektion aufrufen oder indem Sie eine eigene Klasse in das java.util -Paket schleichen. Die Java-Betreuer könnten diese Methode in Zukunft wegnehmen, und sie ist möglicherweise nicht auf allen Plattformen vorhanden, aber wenn Sie bereit sind, Ihre Nase zu halten und das Risiko einzugehen, ist dies eine einfache Lösung.

    
Tom Anderson 07.10.2012, 15:23
quelle
3

NavigableMap hat ceilingKey , wodurch Sie equals für den zurückgegebenen Schlüssel verwenden können, um zu sehen, ob es einen Eintrag für diesen genauen Schlüssel gibt. Aber Sie könnten HashMap nicht verwenden, Sie benötigen TreeMap oder etwas, das die Speicherleistungsvorteile zunichtemacht (und Ihre Schlüssel müssen Comparable implementieren). Außerdem sagt das Javadoc nicht, ob der zurückgegebene Schlüssel das exakt gleiche Objekt ist, das in der Map verwendet wird, daher könnte es umsetzungsspezifisch sein.

    
artbristol 07.10.2012 15:39
quelle
1

Bearbeiten : Was ich denke, dass du es machen willst, ist test-effizient, wenn key-Object ein Schlüssel in dir ist Map :

%Vor%

Alte Antwort:

%Vor%

Map#keySet() gibt eine Set zurück, die alle verwendeten Schlüssel in der Karte enthält. Sie können durch Ihr Set iterieren. Ein Set ist nicht so angeordnet wie dein Map auch nicht. Aber Sie können es in ein Array mit Set#toArray() konvertieren, das ein Array von Objekten zurückgibt, die in den generischen Typ von Set umgewandelt werden können.

    
Simulant 07.10.2012 14:22
quelle
0

Ich schlage vor, Sie nähern sich so.

%Vor%     
PbxMan 07.10.2012 14:25
quelle
0

Sie möchten den Eintrag so einstellen wie es scheint.

%Vor%

Sie werden nicht besser werden, ohne einige Informationen über Ihre Daten zu nutzen.

Außerdem ist die API-Dokumentation Ihr Freund.

    
Dunes 07.10.2012 14:39
quelle
0

Wenn Sie das Key zu einem gegebenen Value benötigen, gibt es drei Möglichkeiten:

  1. Iteriere über den Schlüsselsatz und finde den Schlüssel zu deinem Wert (schlechte Laufzeit).
  2. Speichern Sie die inverse Karte zusätzlich zu Ihrer ursprünglichen Karte (Wert - & gt; Key) (doppelter Speicherplatzverbrauch)
  3. Verwenden Sie Guavas HashBiMap , das eine Methode inverse . Es wird die Umkehrung Ihrer Karte zurückgeben. Dann können Sie einfach inverse.get(value) verwenden, um Ihren Schlüssel zu erhalten.
Baz 07.10.2012 14:58
quelle
0

Sie können die Werte in der Karte als Paar beibehalten: Eingabe & lt; Schlüssel, Wert & gt;

%Vor%

und teilen Sie den Schlüssel mit dem Eintrag, wenn Sie ihn zuordnen.

    
GKislin 15.04.2016 12:02
quelle
0

Ich habe eine andere Problemumgehung gefunden, indem ich die Implementierung der Element- (oder Schlüssel-) Vergleiche in den Sammlungen (oder Karten) ausnutze.

Alle Collections (oder Maps) Implementierungen in java.util (soweit ich weiß) vergleichen Elemente nach o.equals(e) , wenn o das vom Benutzer gesuchte Objekt ist. Also habe ich folgende Lösung gefunden:

%Vor%

Die Sammlung (oder Karte) ruft die Methode OriginalElementExtractor.equals(Object) auf, um nach Gleichheit zu suchen, und das ursprüngliche Element wird übergeben.

    
BarakUgav61 02.06.2016 22:23
quelle

Tags und Links