HashMap und int als Schlüssel

104

Ich versuche eine HashMap zu erstellen, die eine Ganzzahl als Schlüssel und Objekte als Werte enthält.

Meine Syntax lautet:

HashMap<int, myObject> myMap = new HashMap<int, myObject>();

Der zurückgegebene Fehler lautet jedoch: - Syntaxfehler für Token "int", Dimensionen, die nach diesem Token erwartet werden - Ich verstehe nicht, warum ich eine Dimension hinzufügen sollte (dh: das int in ein Array verwandeln), da ich nur eine Ziffer speichern muss als Schlüssel.

Was könnte ich tuen?

Danke im Voraus! :) :)

MrD
quelle
14
HashMapbehandelt keine Grundelemente, nur Objekte.
Menno
Verwandte SO-Frage , aber mit intdem Wert, nicht der Schlüssel.
Cyroxx
4
Verwenden Sie Integerstattdessen.
Hot Licks
Ist es besser, int in Integer zu autoboxen oder Daten einfach als String zu speichern, was komfortabler ist?
Marcin Erbel

Antworten:

25

Sie können kein Grundelement verwenden, da HashMap das Objekt intern für den Schlüssel verwendet. Sie können also nur ein Objekt verwenden, das von Object erbt (dh ein beliebiges Objekt).

Das ist die Funktion put () in HashMap und wie Sie sehen, verwendet sie Object for K:

public V put(K key, V value) {
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

Der Ausdruck "k = e.key" sollte es klar machen.

Ich schlage vor, einen Wrapper wie Integer und Autoboxing zu verwenden.

user1883212
quelle
136

Verwenden Sie Integerstattdessen.

HashMap<Integer, MyObject> myMap = new HashMap<Integer, MyObject>();

Java kopiert Ihre intprimitiven Werte automatisch automatisch in IntegerObjekte.

Weitere Informationen zum Autoboxen in Oracle Java-Dokumentationen.

gaborsch
quelle
10
Er sollte auch keine Klasse nennenmyObject
Adam Gent
@ AdamGent Richtig. Alle Klassennamen sollten mit Großbuchstaben beginnen. Ich habe den empfohlenen Code korrigiert.
Gaborsch
3
Ich weiß, dass du es weißt :) Ich möchte nur sicherstellen, dass das OP weiß / lernt. Soweit ich weiß, hätte er einen Variablennamen in den Typparameter einfügen können.
Adam Gent
1
Nur eine kurze kleine Anmerkung, es ist besser, ArrayMapoder SimpleArrayMapauf Android zu verwenden, um Speicherplatz zu sparen und die Leistung zu steigern ( Weitere Informationen )
Noah Huppert
42

Für alle, die Java für Android-Geräte codieren und hier landen: Verwenden Sie es SparseArrayfür eine bessere Leistung;

private final SparseArray<myObject> myMap = new SparseArray<myObject>();

mit diesem können Sie int anstelle von Integer wie verwenden;

int newPos = 3;

myMap.put(newPos, newObject);
myMap.get(newPos);
Stepoid
quelle
7
Denken Sie daran, dass SparseArray langsamer als Hashmap ist, aber speichereffizienter. Verwenden Sie es also nicht für große Datenmengen.
TpoM6oH
Wie wird SparseArray für eine bessere Leistung verwendet, während es langsamer ist? Welches in meinem Android-Spiel zu verwenden
Snake
@Snake SparseArrayWenn Sie wie bei a eine Reihe von Speicherboxen und Unboxing-Ints zuweisen HashMap, muss die VM die Ausführung für die Speicherbereinigung früher anhalten. Dies ist wichtig, wenn Sie versuchen, häufig und schnell etwas zu tun.
Jon
1
Beachten Sie, dass die Komplexität des Einsetzens in SparseArrayist O (n) ( HashMaphat O (1) ). Es ist wichtig, wenn die Anzahl der Elemente groß ist. Das Einfügen in den Anfang eines solchen Arrays ist viel langsamer.
Vladimir Petrakovich
1
@ M.kazemAkhgary Nicht genau. put()nimmt O(n)(nicht n log n) zum Einfügen beim Start, weil es die Position findet und dann alle folgenden Elemente verschiebt. delete()selbst dauert zwar O(log n), aber das nächste Einfügen oder Durchlaufen von Elementen nach dem Löschen erfordert eine Garbage Collection, die dauert O(n).
Vladimir Petrakovich
5

Sie können versuchen, Trove zu verwenden http://trove.starlight-systems.com/
TIntObjectHashMap ist wahrscheinlich das, wonach Sie suchen.

Arek
quelle
4

Der Hauptgrund dafür, dass HashMap kein Grundelement als Schlüssel zulässt, besteht darin, dass HashMap so konzipiert ist, dass zum Vergleichen der Schlüssel die Methode equals () verwendet wird und eine Methode nur für ein Objekt aufgerufen werden kann, das sich nicht auf einem Grundelement befindet.

Wenn int automatisch an Integer gesendet wird, kann Hashmap die Methode equals () für das Integer-Objekt aufrufen .

Aus diesem Grund sollten Sie Integer anstelle von int verwenden. Ich meine, Hashmap löst einen Fehler aus, während int als Schlüssel eingegeben wird (Sie kennen die Bedeutung des ausgelösten Fehlers nicht).

Und wenn Sie der Meinung sind, dass Sie die Map-Leistung beschleunigen können, indem Sie ein Grundelement als Schlüssel erstellen , gibt es eine Bibliothek namens FastUtil, die eine Map-Implementierung mit dem Typ int als Schlüssel enthält.

Aus diesem Grund ist es viel schneller als Hashmap

Pater Mathew
quelle
1
Nein, der Hauptgrund für nicht erlaubt Urtyp ist Typ Löschung in Java, die effektiv verwandelt sich Map<Integer, String>in Map<Object, Object>während der Kompilierung. Übrigens gibt es IdentityHashMap, das einen ==Operator zur Gleichheitsprüfung verwendet, der primitive Typen immer noch nicht zulässt.
Yoory N.
3

HashMap erlaubt keine primitiven Datentypen als Argumente. Es können also nur Objekte akzeptiert werden

HashMap<int, myObject> myMap = new HashMap<int, myObject>();

wird nicht funktionieren.

Sie müssen die Deklaration in ändern

HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();

Also auch wenn Sie Folgendes tun

myMap.put(2,myObject);

Der primitive Datentyp wird automatisch an ein Integer-Objekt angehängt.

8 (int) === boxing ===> 8 (Integer)

Weitere Informationen zum Autoboxen finden Sie hier http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

Lakshmi
quelle
1

Verwenden Sie int als Objekt und nicht als primitiven Typ

HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();
franki3xe
quelle
Ich habe HashMap <Integer, MyObject> geschrieben. MyMap = new HashMap <Integer, MyObject> (); aber das Anzeigen machen mein Problem mit> und <, um eine gute Antwort anzuzeigen
franki3xe
Ich weiß, dass es schmerzhaft ist zu tippen, aber ich habe versucht, dich sofort zu retten -1. Ich kommentiere im Gegensatz zu anderen vor der Bestrafung (ich habe dich nicht -1).
Adam Gent
0

Benutzen Sie bitte HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();

Michael
quelle
0

Ich verstehe nicht, warum ich eine Dimension hinzufügen sollte (dh das int in ein Array verwandeln), da ich nur eine Ziffer als Schlüssel speichern muss.

Ein Array ist auch ein Objekt, also HashMap<int[], MyObject>ein gültiges Konstrukt, das int-Arrays als Schlüssel verwendet.

Der Compiler weiß nicht, was Sie wollen oder was Sie brauchen, er sieht nur ein Sprachkonstrukt, das fast korrekt ist, und warnt, was fehlt, damit es vollständig korrekt ist.

Yoory N.
quelle
1
Seien Sie vorsichtig, der Hash-Wert eines Arrays hängt nicht mit seinem Inhalt zusammen, sodass zwei Arrays mit demselben Inhalt auf einen anderen Wert hashen können, was es zu einem sehr schlechten Schlüssel macht.
John16384
0

Für jemanden, der an einer solchen Karte interessiert ist, weil Sie den Platzbedarf von Autoboxen in Java von Wrappern über Primitivtypen reduzieren möchten , würde ich die Verwendung von Eclipse-Sammlungen empfehlen . Trove wird nicht mehr unterstützt , und ich glaube, es ist eine ziemlich unzuverlässige Bibliothek (obwohl sie sowieso sehr beliebt ist) und kann nicht mit Eclipse-Sammlungen verglichen werden .

import org.eclipse.collections.impl.map.mutable.primitive.IntObjectHashMap;

public class Check {
    public static void main(String[] args) {
        IntObjectHashMap map = new IntObjectHashMap();

        map.put(5,"It works");
        map.put(6,"without");
        map.put(7,"boxing!");

        System.out.println(map.get(5));
        System.out.println(map.get(6));
        System.out.println(map.get(7));
    }
}

In diesem Beispiel oben IntObjectHashMap .

Wie Sie braucht INT-> Objekt - Mapping, sollte auch Verwendung von YourObjectType[]Array oder List<YourObjectType>und Zugriffs Werten von Index, als Karte ist von Natur aus einem assoziativen Array mit int - Typ als Index.

Alex
quelle