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 drei 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 beiden folgenden 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);
java
data-structures
mario595
quelle
quelle
class PriceKey{ PriceType type; PriceSubtype subtype; }
Schlüssel. Dies kann dann leicht weiter verlängert werdenAntworten:
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 Karten 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 durch
[ (key, value) for (key, value) in prices.items() if key.startswith('A') ]
. Dies 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
bis erweitert(type, subtype)
. Gibt es eine Chance, die die nächste Umdrehung braucht(type, subtype, variation)
oder(type, subtype, version)
? 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".quelle
key.startswith('RXR')
Tests, die ich erwähnt habe. Verschachtelte Karten sind immer O (1) -Operationen und erfordern weder den Aufwand für das Vorsortieren der Karte noch für Zeichenfolgenvergleiche.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 viel Speicherplatz beanspruchen. Wenn Sie eine Karte mit noch mehr Karten füllen, wird das Problem des Speicherverbrauchs 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.
quelle
Dies hat weniger mit "welche Implementierung am besten ist" als vielmehr mit "mit welcher Abstraktion soll ich arbeiten" 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.
quelle
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:
Type
diese Tabelle aussehen würdeType(INT auto_inc id, VARCHAR(255) name, VARCHAR(255) desc, INT status, etc)
Price
Verwenden Sie in Ihrer Tabelle einen Fremdschlüssel für dieType
obige Tabelle, damit es so aussiehtPrice(INT type_id, INT price)
inactive
da das Löschen aufgrund der baumelnden Referenzen zu echten Kopfschmerzen führen würdeJetzt können Benutzer- und Geschäftslogik dem Schema eine beliebige Typ-Subtyp-Kombination hinzufügen. Sie müssten lediglich eine neue Zeile in der
Type
Tabelle erstellen und diesename
und / oderdesc
die alte Tabelle ändern .In Ihrem Fall würde der Benutzer den Typ
A
in Typ umbenennenA_1
, einen neuen Typ namens hinzufügenA_2
und einen neuen Preis fürA_2
as festlegen15
quelle