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.

0voto

Jan Wiemer Punkte 31

Eine andere mögliche Lösung, die die Möglichkeit von komplizierteren Schlüsseln bietet, finden Sie hier: http://insidecoffe.blogspot.de/2013/04/indexable-hashmap-implementation.html

0voto

kon psych Punkte 586

Ich würde die folgende Struktur vorschlagen

Map<K1, Map<K2, V>>

obwohl die Suche nach dem zweiten Schlüssel möglicherweise nicht effizient ist

0voto

Stephen Punkte 18898

Es scheint mir, dass die Methoden, die Sie in Ihrer Frage wünschen, direkt von Map. Die Methoden, die Sie anscheinend benötigen, sind

put(K1 key, K2 key, V value)
put(K1 key, V value)
put(K2 key, V value)

Beachten Sie, dass in map, get() y containsKey() usw. nehmen alle Object Argumente. Es hindert Sie nichts daran, das eine Argument zu verwenden. get() Methode, um an alle zusammengesetzten Maps zu delegieren, die Sie kombinieren (wie in Ihrer Frage und anderen Antworten erwähnt). Vielleicht müssten Sie Typregistrierung, so dass Sie nicht bekommen Klasse Casting Probleme (wenn sie speziell + naiv implementiert sind.

Eine Registrierung auf der Grundlage von Eingaben würde es auch ermöglichen, die "richtige" Karte abzurufen, die verwendet werden soll:

Map<T,V> getMapForKey(Class<T> keyClass){
  //Completely naive implementation - you actually need to 
  //iterate through the keys of the maps, and see if the keyClass argument
  //is a sub-class of the defined map type.  And then ordering matters with 
  //classes that implement multiple interfaces...
  Map<T,V> specificTypeMap = (Map<T,V) maps.get(keyClass);
  if (specificTypeMap == null){
     throw new IllegalArgumentException("There is no map keyed by class" + keyClass);
  }
  return maps.get(keyClass);
}

V put(Object key, V value) {
  //This bit requires generic suppression magic - but 
  //nothing leaves this class and you're testing it right? 
  //(You can assert that it *is* type-safe)
  Map map = getMapForKey(key.getClass());
  map.put(object, key);
}

void put(Object[] keys, V value) { //Or put(V value, Object ... keys)
   //Might want to catch exceptions for unsupported keys and log instead?
   .....
}

Nur ein paar Ideen...

0voto

Kevin Peterson Punkte 7069

Je nach Verwendungszweck können Sie dies entweder mit zwei Karten tun Map<K1, V> y Map<K2, V> oder mit zwei Karten Map<K1, V> y Map<K2, K1> . Wenn einer der Schlüssel dauerhafter ist als der andere, kann die zweite Option sinnvoller sein.

0voto

Dima Punkte 3968

Wenn Sie beabsichtigen, eine Kombination von mehreren Schlüsseln als einen zu verwenden, dann sollten Sie vielleicht Apache Commons MultiKey ist Ihr Freund. Ich glaube aber nicht, dass es eins zu eins funktionieren würde.

0 Stimmen

Ich würde JEDEM von Apache Collections abraten. Seit fast 6 Jahren haben wir Java 5 mit seinen generischen Typen, die Apache Collections nicht unterstützt.

0 Stimmen

... und sie brechen die Schnittstellenkonventionen ziemlich stark - siehe MultiMap (und wie es unmöglich wäre, daraus eine Map<K,V> zu machen)

3 Stimmen

Tatsächlich wurde commons collections geforkt, um Generika zu unterstützen, siehe dieses Projekt hier: sourceforge.net/projects/collections

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