185 Stimmen

Wie implementiert man eine Karte mit mehreren Schlüsseln?

Ich brauche eine Datenstruktur, die sich wie eine Map verhält, aber mehrere (unterschiedlich typisierte) Schlüssel für den Zugriff auf ihre Werte verwendet.
(Lassen Sie uns nicht zu allgemein sein, sagen wir zwei Tasten)

Die Einzigartigkeit der Schlüssel ist garantiert.

Etwa so:

MyMap<K1,K2,V> ...

Mit Methoden wie:

getByKey1(K1 key)...
getByKey2(K2 key)...
containsKey1(K1 key)...
containsKey2(K2 key)...

Haben Sie irgendwelche Vorschläge?

Das Einzige, was mir einfällt, ist:
Schreiben Sie eine Klasse, die intern zwei Maps verwendet.

EDIT Einige Leute schlagen mir vor, eine Tupel , a Paar oder ähnlich als Schlüssel für Java's Map, aber das würde nicht funktionieren für mich:
Ich muss, wie oben geschrieben, in der Lage sein, Werte nur nach einem der beiden angegebenen Schlüssel zu suchen.
Maps verwenden Hash-Codes von Schlüsseln und überprüfen deren Gleichheit.

0 Stimmen

Ich bin erstaunt, dass diese Frage trotz fast 200.000 Aufrufen noch nicht verbessert wurde.

7voto

Vorschlag, wie von einigen Antwortenden vorgeschlagen:

public interface IDualMap<K1, K2, V> {

    /**
    * @return Unmodifiable version of underlying map1
    */
    Map<K1, V> getMap1();

    /**
    * @return Unmodifiable version of underlying map2
    */
    Map<K2, V> getMap2();

    void put(K1 key1, K2 key2, V value);

}

public final class DualMap<K1, K2, V>
        implements IDualMap<K1, K2, V> {

    private final Map<K1, V> map1 = new HashMap<K1, V>();

    private final Map<K2, V> map2 = new HashMap<K2, V>();

    @Override
    public Map<K1, V> getMap1() {
        return Collections.unmodifiableMap(map1);
    }

    @Override
    public Map<K2, V> getMap2() {
        return Collections.unmodifiableMap(map2);
    }

    @Override
    public void put(K1 key1, K2 key2, V value) {
        map1.put(key1, value);
        map2.put(key2, value);
    }
}

3voto

Mike Kucera Punkte 2003

Warum lässt man nicht einfach die Anforderung fallen, dass der Schlüssel ein bestimmter Typ sein muss, d.h. man verwendet einfach Map<Object,V>.

Manchmal sind Generika die zusätzliche Arbeit einfach nicht wert.

3voto

user454322 Punkte 6564

Ich empfehle etwas in dieser Art:

    public class MyMap {

      Map<Object, V> map = new HashMap<Object, V>();

      public V put(K1 key,V value){
        return map.put(key, value);
      }

      public V put(K2 key,V value){
        return map.put(key, value);
      }

      public V get(K1 key){    
        return map.get(key);
      }

      public V get(K2 key){    
        return map.get(key);
      }

      //Same for conatains

    }

Dann können Sie es wie folgt verwenden:
myMap.put(k1,value) o myMap.put(k2,value)

Vorteile : Sie ist einfach, erzwingt Typensicherheit und speichert keine wiederholten Daten (wie die beiden Maps-Lösungen, die allerdings immer noch doppelte Werte speichern).
Beeinträchtigungen : Nicht generisch.

0 Stimmen

Dies ist eigentlich die beste Antwort auf die gestellte Frage, obwohl ich denke, dass die Absicht im Allgemeinen darin besteht, zwei Schlüssel gleichzeitig zu liefern, so dass eine Methode put(K1 key, K2 key, V value) erforderlich ist. Ich glaube, man könnte es auch generisch machen, indem man <K1,K2> zur Klassendefinition hinzufügt, intern sollte die Verwendung von Object (oder besser noch ?) in Ordnung sein.

2voto

AlexVPerl Punkte 7155

Sowohl MultiMap als auch MultiKeyMap von Commons oder Guava werden funktionieren.

Eine schnelle und einfache Lösung könnte jedoch darin bestehen, die Klasse Map buy zu erweitern und selbst einen zusammengesetzten Schlüssel zu verarbeiten, da die Schlüssel vom primitiven Typ sind.

6 Stimmen

-1 Dies ist keine Antwort auf die Frage. Der Fragesteller benötigt keinen zusammengesetzten Schlüssel, sondern zwei verschiedene Einzelschlüssel, die auf dasselbe Objekt verweisen, aber sozusagen als ein Eintrag verwaltet werden. Lesen Sie die Frage noch einmal. MultiKeyMap ist nett, aber nur für zusammengesetzte Schlüssel geeignet.

1 Stimmen

Hat die Frage von OP nicht beantwortet, aber meine schon...

1 Stimmen

Der OP möchte nicht mit SchlüsselA und SchlüsselB zuordnen, sondern mit SchlüsselA oder SchlüsselB

2voto

bram Punkte 21

Alle Mehrfachschlüssel schlagen wahrscheinlich fehl, da put([key1, key2], val) und get([null, key2]) am Ende die Gleichheit von [key1, key2] und [null, key2] verwenden. Wenn die Backing-Map doesnt enthält Hash-Buckets pro Schlüssel dann Lookups sind wirklich langsam zu.

Ich denke, der Weg zu gehen ist mit einem Index-Dekorator (siehe die key1, key2 Beispiele oben) und wenn die zusätzlichen Index-Schlüssel Eigenschaften des gespeicherten Wertes sind, können Sie die Eigenschaft Namen und Reflexion verwenden, um die Secondairy-Maps zu bauen, wenn Sie put(key, val) und fügen Sie eine zusätzliche Methode get(propertyname, propertyvalue), um diesen Index zu verwenden.

der Rückgabetyp von get(Eigenschaftsname, Eigenschaftswert) könnte eine Sammlung sein, so dass auch nicht eindeutige Schlüssel indiziert werden....

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X