Aufgrund Ihrer letzten Änderung sollten Sie in dieser Situation Instanzen der Klasse A als Schlüssel verwenden. Lookups werden basierend auf der Semantik von equals()
und hashCode()
durchgeführt, so dass dies dazu führt, dass Instanzen nur von den "Schlüsselfeldern" abgerufen werden. Daher würde der folgende Code arbeiten, wie Sie beabsichtigen:
final Map<A, String> map = new HashMap<A, Object>();
final A first = new A("fe", "fi", "fo", "fum");
map.put(first, "success");
// later on
final A second = new A ("fe", "fi", "foo", "bar");
System.out.println(map.get(second)); // prints "success";
Having said that, Ihre Beschreibung der Option 2 macht mich ein wenig besorgt, dass dies nicht die vernünftigste Option sein könnte. Wenn Sie eine Map<A, String>
erstellen, ist dies eine Zuordnung von Instanzen der Klasse A zu Strings. Ihr zweiter Punkt impliziert jedoch, dass Sie es als eine Zuordnung von Paaren von Schlüsselfeldern zu Strings vorstellen möchten. Wenn Sie in der Regel Werte nach ein paar "rohen" Strings suchen, würde ich davon abraten. Es fühlt sich falsch an (für mich), eine "falsche" Instanz von A zu erstellen, nur um eine Suche durchzuführen - in diesem Fall sollten Sie wahrscheinlich eine Schlüsselklasse erstellen, die das Paar von Zeichenfolgen enthält, wie in Option 1 beschrieben Sie können sogar Instanzen dieser Objekte in Ihre A
Objekte einbetten, um die Schlüsselfelder zu halten.
Es gibt ein ähnliches Argument für oder gegen Option 3. Wenn die Strings wirklich konzeptuell hierarchisch sind, könnte das durchaus Sinn machen. Zum Beispiel, wenn field1
war Land, und field2
war Town, könnte man definitiv argumentieren, dass die verschachtelte Karten sinnvoll sind - Sie haben eine Zuordnung von Land, um die Karte von Stadt-> A-Beziehungen innerhalb des Landes. Aber wenn Ihre Schlüssel nicht auf diese Weise natürlich zusammengesetzt werden (sagen wir, wenn sie (x, y) -Koordinaten wären), wäre dies wiederum kein sehr natürlicher Weg, um die Daten darzustellen, und eine einstufige Karte von XYPoint
zu bewerten wäre vernünftiger. (Ebenso, wenn Sie nie verwenden Sie die zweistufige Karte mit Ausnahme von immer durch beide Ebenen gehen, könnte man argumentieren, die einstufige Karte macht noch mehr Sinn.)
Und schließlich, wie für Option 4 -if Du bist immer Mapping zu A
selbst, und speichert den Schlüssel als seinen eigenen Wert (zB wenn Sie Ihre A
Instanzen kanonisieren möchten, ein bisschen wie String.intern()
) dann wie Sie darauf hingewiesen wurde, müssen Sie kein Map
überhaupt verwenden, und ein Set
wird hier die Arbeit machen. Die Map
ist nützlich, wenn Sie Beziehungen zwischen verschiedenen Objekte herstellen möchten, während eine Set
automatisch die Einzigartigkeit von Objekten ohne zusätzlichen konzeptionellen Aufwand bietet.
Wenn Sie tun, um die Klasse selbst als Schlüssel verwenden, gewarnt werden, dass auch nur im allgemeinen verwendet werden als Schlüssel-Objekte sollten, wenn ihre hashCode
(und das Verhalten von equals
) nicht im Laufe der Zeit ändern. Typischerweise bedeutet dies, dass die Schlüssel unveränderbar sind, obwohl Sie es sich hier leisten könnten, veränderliche "Nicht-Schlüssel" -Felder zu haben. Wenn Sie diese Regel zu brechen, würde man seltsame Verhalten wie die folgenden:
// Populate a map, with an A as the key
final Map<A, String> map = new HashMap<A, Object>();
final A a = new A("one", "two", "three", "four");
map.put(a, "here");
// Mutate a
a.setField1("un");
// Now look up what we associated with it
System.out.println(map.get(a)); // prints "null" - huh?
System.out.println(map.containsKey(a)); // prints "false"
Sie müssen die Klasse oder Instanzen dieser Klasse speichern? Wenn Sie Objekte getrennt speichern möchten, können Sie HashSet verwenden. – khachik
Instanzen dieser Klasse (Bearbeitung der Frage). Wie kann ich eine Instanz von einem HashSet abrufen, wenn ich nur field1 und field2 habe? – Russell