Chromium Code Reviews| 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..6661dfba7e64efb50235ea357024022db7d0bb3e |
| --- /dev/null |
| +++ b/pkg/collection/lib/src/canonicalized_map.dart |
| @@ -0,0 +1,94 @@ |
| +// 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 'utils.dart'; |
| + |
| +/** |
| + * A map whose keys are converted to canonical values of type `C`. |
| + * |
| + * 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. |
|
Lasse Reichstein Nielsen
2014/07/01 09:18:15
each once -> each key once
nweiz
2014/07/01 21:21:44
Done.
|
| + */ |
|
Lasse Reichstein Nielsen
2014/07/01 09:18:15
Document whether the Map allows null as a key (afa
nweiz
2014/07/01 21:21:44
Done.
|
| +class CanonicalizedMap<C, K, V> implements Map<K, V> { |
| + final Function _canonicalize; |
| + |
| + final _base = new Map<C, Pair<K, V>>(); |
| + |
| + /** |
| + * 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 equivalent. |
| + */ |
| + CanonicalizedMap(C canonicalize(K key)) |
| + : _canonicalize = canonicalize; |
| + |
| + /** |
| + * Creates a canonicalized map that is initialized with the key/value pairs of |
| + * [other]. |
| + * |
| + * The [canonicalize] function should return the canonical value for the given |
| + * key. Keys with the same canonical value are considered equivalent. |
| + */ |
| + CanonicalizedMap.from(Map<K, V> other, C canonicalize(K key)) |
| + : _canonicalize = canonicalize { |
| + addAll(other); |
| + } |
| + |
| + V operator [](Object key) { |
| + if (key != null && key is! K) return null; |
| + var pair = _base[_canonicalize(key)]; |
| + return pair == null ? null : pair.last; |
| + } |
| + |
| + void operator []=(K key, V value) { |
| + _base[_canonicalize(key)] = new Pair(key, value); |
| + } |
| + |
| + void addAll(Map<K, V> other) { |
| + other.forEach((key, value) => this[key] = value); |
| + } |
| + |
| + void clear() => _base.clear(); |
|
Lasse Reichstein Nielsen
2014/07/01 09:18:15
I'd prefer "{...}" to "=>" for a void function.
nweiz
2014/07/01 21:21:44
Done.
|
| + |
| + bool containsKey(Object key) { |
| + if (key != null && key is! K) return null; |
| + return _base.containsKey(_canonicalize(key)); |
| + } |
| + |
| + bool containsValue(Object value) => |
| + _base.values.any((pair) => pair.last == value); |
| + |
| + void forEach(void f(K key, V value)) { |
| + _base.forEach((key, pair) => f(pair.first, pair.last)); |
| + } |
| + |
| + bool get isEmpty => _base.isEmpty; |
| + |
| + bool get isNotEmpty => _base.isNotEmpty; |
| + |
| + Iterable<K> get keys => _base.values.map((pair) => pair.first); |
| + |
| + int get length => _base.length; |
| + |
| + V putIfAbsent(K key, V ifAbsent()) { |
| + return _base.putIfAbsent(_canonicalize(key), |
| + () => new Pair(key, ifAbsent())).last; |
| + } |
| + |
| + V remove(Object key) { |
| + if (key != null && key is! K) return null; |
| + var pair = _base.remove(_canonicalize(key)); |
| + return pair == null ? null : pair.last; |
| + } |
| + |
| + Iterable<K> get values => _base.values.map((pair) => pair.last); |
| + |
| + String toString() => "{" + |
| + _base.values.map((pair) => "${pair.first}: ${pair.last}").join(", ") + |
| + "}"; |
|
Lasse Reichstein Nielsen
2014/07/01 09:18:15
Just use:
String toString() => Maps.mapToString
nweiz
2014/07/01 21:21:44
Done.
|
| +} |