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

Unified Diff: sdk/lib/_internal/lib/collection_patch.dart

Issue 23893002: Add custom equals and hashCode for HashMap implementation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 7 years, 3 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
« no previous file with comments | « runtime/lib/collection_patch.dart ('k') | sdk/lib/collection/hash_map.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/lib/collection_patch.dart
diff --git a/sdk/lib/_internal/lib/collection_patch.dart b/sdk/lib/_internal/lib/collection_patch.dart
index cbcf114ab898d882adc22dc4bed4c41da32f2c5e..93557043c0e2169adbc191a72dedd248e41b635a 100644
--- a/sdk/lib/_internal/lib/collection_patch.dart
+++ b/sdk/lib/_internal/lib/collection_patch.dart
@@ -6,6 +6,23 @@
import 'dart:_foreign_helper' show JS;
patch class HashMap<K, V> {
+ patch factory HashMap({ bool equals(K key1, K key2), int hashCode(K key) }) {
+ if (hashCode == null) {
+ if (equals == null) {
+ return new _HashMapImpl<K, V>();
+ }
+ if (identical(identical, equals)) {
+ return new _IdentityHashMap<K, V>();
+ }
+ hashCode = _defaultHashCode;
+ } else if (equals == null) {
+ equals = _defaultEquals;
+ }
+ return new _CustomHashMap<K, V>(equals, hashCode);
+ }
+}
+
+class _HashMapImpl<K, V> implements HashMap<K, V> {
int _length = 0;
// The hash map contents are divided into three parts: one part for
@@ -26,21 +43,21 @@ patch class HashMap<K, V> {
// guard against concurrent modifications.
List _keys;
- patch HashMap._internal();
+ _HashMapImpl();
- patch int get length => _length;
- patch bool get isEmpty => _length == 0;
- patch bool get isNotEmpty => !isEmpty;
+ int get length => _length;
+ bool get isEmpty => _length == 0;
+ bool get isNotEmpty => !isEmpty;
- patch Iterable<K> get keys {
+ Iterable<K> get keys {
return new HashMapKeyIterable<K>(this);
}
- patch Iterable<V> get values {
+ Iterable<V> get values {
return keys.map((each) => this[each]);
}
- patch bool containsKey(Object key) {
+ bool containsKey(Object key) {
if (_isStringKey(key)) {
var strings = _strings;
return (strings == null) ? false : _hasTableEntry(strings, key);
@@ -55,17 +72,17 @@ patch class HashMap<K, V> {
}
}
- patch bool containsValue(Object value) {
+ bool containsValue(Object value) {
return _computeKeys().any((each) => this[each] == value);
}
- patch void addAll(Map<K, V> other) {
+ void addAll(Map<K, V> other) {
other.forEach((K key, V value) {
this[key] = value;
});
}
- patch V operator[](Object key) {
+ V operator[](Object key) {
if (_isStringKey(key)) {
var strings = _strings;
return (strings == null) ? null : _getTableEntry(strings, key);
@@ -81,7 +98,7 @@ patch class HashMap<K, V> {
}
}
- patch void operator[]=(K key, V value) {
+ void operator[]=(K key, V value) {
if (_isStringKey(key)) {
var strings = _strings;
if (strings == null) _strings = strings = _newHashTable();
@@ -112,14 +129,14 @@ patch class HashMap<K, V> {
}
}
- patch V putIfAbsent(K key, V ifAbsent()) {
+ V putIfAbsent(K key, V ifAbsent()) {
if (containsKey(key)) return this[key];
V value = ifAbsent();
this[key] = value;
return value;
}
- patch V remove(Object key) {
+ V remove(Object key) {
if (_isStringKey(key)) {
return _removeHashTableEntry(_strings, key);
} else if (_isNumericKey(key)) {
@@ -140,14 +157,14 @@ patch class HashMap<K, V> {
}
}
- patch void clear() {
+ void clear() {
if (_length > 0) {
_strings = _nums = _rest = _keys = null;
_length = 0;
}
}
- patch void forEach(void action(K key, V value)) {
+ void forEach(void action(K key, V value)) {
List keys = _computeKeys();
for (int i = 0, length = keys.length; i < length; i++) {
var key = JS('var', '#[#]', keys, i);
@@ -240,7 +257,7 @@ patch class HashMap<K, V> {
return key is num && JS('bool', '(# & 0x3ffffff) === #', key, key);
}
- static int _computeHashCode(var key) {
+ int _computeHashCode(var key) {
// We force the hash codes to be unsigned 30-bit integers to avoid
// issues with problematic keys like '__proto__'. Another option
// would be to throw an exception if the hash code isn't a number.
@@ -280,12 +297,12 @@ patch class HashMap<K, V> {
JS('void', 'delete #[#]', table, key);
}
- static List _getBucket(var table, var key) {
+ List _getBucket(var table, var key) {
var hash = _computeHashCode(key);
return JS('var', '#[#]', table, hash);
}
- static int _findBucketIndex(var bucket, var key) {
+ int _findBucketIndex(var bucket, var key) {
if (bucket == null) return -1;
int length = JS('int', '#.length', bucket);
for (int i = 0; i < length; i += 2) {
@@ -308,6 +325,39 @@ patch class HashMap<K, V> {
}
}
+class _IdentityHashMap<K, V> extends _HashMapImpl<K, V> {
+ int _findBucketIndex(var bucket, var key) {
+ if (bucket == null) return -1;
+ int length = JS('int', '#.length', bucket);
+ for (int i = 0; i < length; i += 2) {
+ if (identical(JS('var', '#[#]', bucket, i), key)) return i;
+ }
+ return -1;
+ }
+}
+
+class _CustomHashMap<K, V> extends _HashMapImpl<K, V> {
+ final Function _equals;
+ final Function _hashCode;
+ _CustomHashMap(this._equals, this._hashCode);
+
+ int _computeHashCode(var key) {
+ // We force the hash codes to be unsigned 30-bit integers to avoid
+ // issues with problematic keys like '__proto__'. Another option
+ // would be to throw an exception if the hash code isn't a number.
+ return JS('int', '# & 0x3ffffff', _hashCode(key));
+ }
+
+ int _findBucketIndex(var bucket, var key) {
+ if (bucket == null) return -1;
+ int length = JS('int', '#.length', bucket);
+ for (int i = 0; i < length; i += 2) {
+ if (_equals(JS('var', '#[#]', bucket, i), key)) return i;
+ }
+ return -1;
+ }
+}
+
class HashMapKeyIterable<E> extends IterableBase<E> {
final _map;
HashMapKeyIterable(this._map);
« no previous file with comments | « runtime/lib/collection_patch.dart ('k') | sdk/lib/collection/hash_map.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698