Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Unified Diff: pkg/collection/lib/src/canonicalized_map.dart

Issue 350183010: Add a CanonicalizedMap class to pkg/collection. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/collection/lib/src/canonicalized_map.dart
diff --git a/pkg/collection/lib/src/canonicalized_map.dart b/pkg/collection/lib/src/canonicalized_map.dart
new file mode 100644
index 0000000000000000000000000000000000000000..8ec48ed68285498609a9caaf54e17b5afa7db3e4
--- /dev/null
+++ b/pkg/collection/lib/src/canonicalized_map.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart.pkg.collection.canonicalized_map;
+
+import '../wrappers.dart';
+
+/**
+ * A map whose keys are converted to canonical values.
+ *
+ * This is useful for using case-insensitive String keys, for example. It's more
+ * efficient than a [LinkedHashMap] with a custom equality operator because it
+ * only canonicalizes each once, rather than doing so for each comparison.
+ */
+class CanonicalizedMap<K, V> extends DelegatingMap<K, V> {
Lasse Reichstein Nielsen 2014/06/27 06:57:47 Could we allow the canonicalization of a key to no
nweiz 2014/06/30 20:37:46 Done.
+ final Function _canonicalize;
+
+ /**
+ * A map from the canonicalized keys to their original values.
+ */
+ final _keys = new Map<K, V>();
Lasse Reichstein Nielsen 2014/06/27 06:57:47 Should be <K,K>. Have you considered using a
nweiz 2014/06/30 20:37:46 Done, using the Pair class that's used elsewhere i
+
+ /**
+ * Creates an empty canonicalized map.
+ *
+ * The [canonicalize] function should return the canonical value for the given
+ * key. Keys with the same canonical value are considered identical, and the
Lasse Reichstein Nielsen 2014/06/27 06:57:47 identical -> equivalent Ditto below.
nweiz 2014/06/30 20:37:46 Done.
+ * canonical values of the keys are stored in the map.
Lasse Reichstein Nielsen 2014/06/27 06:57:47 "stored in the map" is vague but sounds significan
nweiz 2014/06/30 20:37:46 I just removed this. It was a holdover from before
+ */
+ CanonicalizedMap(K canonicalize(K key))
Lasse Reichstein Nielsen 2014/06/27 06:57:47 I'd also like to have an "bool isValidKey(Object o
Lasse Reichstein Nielsen 2014/06/27 06:57:47 Please see if you can also make the map a paramete
nweiz 2014/06/30 20:37:46 I don't completely understand the purpose of this
nweiz 2014/06/30 20:37:46 I don't think it's worth complicating the API to s
Lasse Reichstein Nielsen 2014/07/01 09:18:14 ACK, if we make the type of canonical object C ins
Lasse Reichstein Nielsen 2014/07/01 09:18:14 I assume that if isValidKey(o) return false, then
nweiz 2014/07/01 21:21:44 Done.
+ : _canonicalize = canonicalize,
+ super({});
+
+ /**
+ * Creates a canonicalized map that contains all key/value pairs of [other].
Lasse Reichstein Nielsen 2014/06/27 06:57:47 Because of the canonicalization, it might contain
nweiz 2014/06/30 20:37:46 Good point. Done.
+ *
+ * The [canonicalize] function should return the canonical value for the given
+ * key. Keys with the same canonical value are considered identical, and the
+ * canonical values of the keys are stored in the map.
+ */
+ CanonicalizedMap.from(Map<K, V> other, K canonicalize(K key))
+ : _canonicalize = canonicalize,
+ super({}) {
+ addAll(other);
+ }
+
+ V operator [](Object key) {
+ if (key != null && key is! K) return null;
+ return super[_canonicalize(key)];
+ }
+
+ void operator []=(K key, V value) {
+ var canonical = _canonicalize(key);
+ _keys[canonical] = key;
+ super[canonical] = value;
+ }
+
+ void addAll(Map<K, V> other) {
+ other.forEach((key, value) => this[key] = value);
+ }
+
+ bool containsKey(Object key) {
+ if (key != null && key is! K) return null;
+ return super.containsKey(_canonicalize(key));
+ }
+
+ void forEach(void f(K key, V value)) {
+ super.forEach((key, value) => f(_keys[key], value));
+ }
+
+ Iterable<K> get keys => _keys.values;
+
+ V putIfAbsent(K key, V ifAbsent()) {
+ var canonical = _canonicalize(key);
+ return super.putIfAbsent(canonical, () {
+ _keys[canonical] = key;
+ return ifAbsent();
+ });
+ }
+
+ V remove(Object key) {
+ if (key != null && key is! K) return null;
+ var canonical = _canonicalize(key);
+ _keys.remove(canonical);
+ return super.remove(canonical);
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698