it-swarm.com.de

Verschachtelte Karten vs. kombinierte Schlüssel

in dem Projekt, an dem ich gerade arbeite, hatten wir drei verschiedene Arten von Preisen, abhängig vom Alter des Benutzers (Erwachsener, Kind usw.). Wir hatten also in der DB einen Tisch, der so aussah:

PRICES
type     Amount
A         20
B         15
C         ..
D         ..

Anfangs hatten wir nur 4 verschiedene Arten von Preisen, also hatten wir im Code so etwas:

Map<String, BigDecimal> prices = new HashMap<String, BigDecimal>();

Wo die Schlüssel waren die Preisart.

Kürzlich haben sie eine neue Geschäftsregel hinzugefügt, die jedem Preistyp 3 Untertypen hinzufügt. Jetzt haben wir so etwas:

PRICES
type   subtype  Amount
A          1      20
A          2      15
A          3      ..
B          1      ..
B          2      ..
...        ..     ..

Welche der folgenden beiden Optionen ist Ihrer Meinung nach besser und warum?

Verschachtelte Karten

Map<String, Map<String, BigDecimal>> prices;

dabei sind die Schlüssel der Preistyp und der Subtyp:

prices.get(type).get(subtype);

Kombinierte Schlüssel

Dieselbe Karte wie ursprünglich:

Map<String, BigDecimal> prices;

Und verketten Sie die Schlüssel, um die verschiedenen Preise zu indizieren:

prices.get(type+"_"+subtype);
8
mario595

Sowohl verschachtelte als auch kombinierte Schlüssel haben ihre Plätze. bowmore gibt ein Pro-Argument für zusammengesetzte Schlüssel und ein Con-Argument für verschachtelte Maps an. Lassen Sie mich die loyale Opposition liefern:

Zusammengesetzte Kartenschlüssel eignen sich hervorragend, wenn Sie nach einem bestimmten bekannten Objekt suchen.

Verschachtelte Karten funktionieren gut, wenn Sie schnell alle Variationen, Arten und Untertypen des Typs A finden müssen. Die Auswahl von A (vs. B, C, ...) kann beispielsweise der erste Schritt in einem Entscheidungsbaum sein. Sobald der Benutzer oder Algorithmus oder was auch immer A auswählt, müssen Sie nur über die Subtypen von A Bescheid wissen, und B..Z oder B..ZZZZZ spielen keine Rolle mehr.

Jetzt haben Sie es mit einer sehr engen und effizienten Suchstruktur für die Subsuche zu tun. Wenn Sie dies mit zusammengesetzten Schlüsseln versuchen, führen Sie am Ende einen vollständigen Tabellenscan a la [ (key, value) for (key, value) in prices.items() if key.startswith('A') ] durch. Das ist keine effiziente Operation und wird langsam sein, wenn die Karte überhaupt groß ist.

Verschachtelte Karten funktionieren auch gut, wenn die Anzahl der Verschachtelungsebenen zunimmt. Die Problemstruktur wurde bereits von type auf (type, subtype) Erweitert. Gibt es eine Chance, dass die nächste Umdrehung (type, subtype, variation) Oder (type, subtype, version) Benötigt? In diesem Fall kann ein verschachtelter Zuordnungsansatz sauber erweitert werden. Dies ist jedoch ein stilistischer Vorteil zweiter Ordnung, insbesondere im Vergleich zu dem oben genannten Vorteil der "einfachen Subsuche".

8
Jonathan Eunice

Vermeiden Sie verschachtelte Karten. Sie sind schwieriger zu skalieren und führen zu Code, der sehr ausführlich und schwer zu lesen ist, wenn alle verschachtelten Generika-Deklarationen ausgeführt werden.

Noch wichtiger ist, dass Maps in Java verbrauchen in der Regel viel Speicher. Wenn Sie eine Map mit noch mehr Maps füllen, wird das Problem mit dem Speicherverbrauch nur noch verschlimmert.

Schließlich ist eine Karte, die zusammengesetzte Schlüssel verwendet, leichter zu überlegen.

Die Verwendung von zusammengesetzten Schlüsseln erleichtert Ihnen in den meisten Fällen das Leben, einige Dinge werden jedoch schwieriger. Sie erhalten beispielsweise alle Preise für eine bestimmte Schlüsselkomponente, aber es ist wahrscheinlicher, dass Sie dieses Ergebnis direkt aus der Datenbank abfragen, als es aus der Karte zu destillieren.

6
bowmore

Dies hat weniger mit "welche Implementierung am besten ist" als vielmehr mit "mit welcher Abstraktion ich arbeiten soll" zu tun.

Sowohl der zusammengesetzte Schlüssel als auch die Karte der Karten haben ihre Stärken und Schwächen, die alle im Bereich der Leistung liegen (dh Geschwindigkeit/Speichernutzung). Sie unterscheiden sich nicht in ihrer Funktionalität: Beide nehmen zwei Werte an und geben den zuvor "put" -Wert zurück.

Da sie funktional gleichwertig sind, sollten Sie sie zuerst abstrahieren. Mach dir keine Sorgen, welches besser ist. Erstellen Sie eine DoubleKeyedMap-Schnittstelle mit allen erforderlichen Methoden und verwenden Sie diese in Ihrem Code. Schreiben Sie dann die Implementierung, die Sie am schnellsten schreiben können, und fahren Sie einfach fort.

NUR wenn Sie Ihre Anwendung geschrieben haben und festgestellt haben, dass Ihre Implementierung des zusammengesetzten Schlüssels nicht sehr schnell nach dem ersten Schlüssel filtert oder dass die Karte der Karten zu viel Speicherplatz beansprucht, wenn Sie sie optimieren.

Vorzeitige Optimierung ist die Wurzel allen Übels. Nicht abstrahieren ist schlimmer.

1
Ben Seidel

Beide Optionen sind meiner Meinung nach nicht gut. Was ist, wenn sich die Geschäftslogik erneut ändert, sodass Sie einen anderen Subtyp haben?

Ich schlage vor, dass Sie Folgendes tun:

  1. Verwenden Sie einen Ersatzschlüssel für einen Tabellenaufruf Type Diese Tabelle würde wie folgt aussehen: Type(INT auto_inc id, VARCHAR(255) name, VARCHAR(255) desc, INT status, etc)
  2. Verwenden Sie in Ihrer Price -Tabelle einen Fremdschlüssel für die obige Type -Tabelle, damit sie wie Price(INT type_id, INT price) aussieht
  3. Stellen Sie sicher, dass Sie das Löschen eines Typs NICHT unterstützen. Sie markieren einfach einen Typ als inactive, da die baumelnden Referenzen das Löschen zu echten Kopfschmerzen machen würden

Jetzt können Benutzer- und Geschäftslogik dem Schema eine beliebige Typ-Subtyp-Kombination hinzufügen. Sie müssten lediglich eine neue Zeile in der Tabelle Type erstellen und name und/oder desc in der alten Tabelle ändern.

In Ihrem Fall würde der Benutzer den Typ A in A_1 Umbenennen, einen neuen Typ mit dem Namen A_2 Hinzufügen und den neuen Preis für A_2 Als 15

0
InformedA