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

Unified Diff: runtime/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 | « no previous file | sdk/lib/_internal/lib/collection_patch.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/lib/collection_patch.dart
diff --git a/runtime/lib/collection_patch.dart b/runtime/lib/collection_patch.dart
index 5bd4ab93657d4ff5f096a3ecdd303661da79e104..f78951f4374bbc044f0dd9df88e391f25985c694 100644
--- a/runtime/lib/collection_patch.dart
+++ b/runtime/lib/collection_patch.dart
@@ -3,23 +3,40 @@
// BSD-style license that can be found in the LICENSE file.
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);
+ }
+}
+
+const int _MODIFICATION_COUNT_MASK = 0x3fffffff;
+
+class _HashMapImpl<K, V> implements HashMap<K, V> {
static const int _INITIAL_CAPACITY = 8;
- static const int _MODIFICATION_COUNT_MASK = 0x3fffffff;
int _elementCount = 0;
List<_HashMapEntry> _buckets = new List(_INITIAL_CAPACITY);
int _modificationCount = 0;
- /* patch */ HashMap._internal();
-
- /* patch */ int get length => _elementCount;
- /* patch */ bool get isEmpty => _elementCount == 0;
- /* patch */ bool get isNotEmpty => _elementCount != 0;
+ int get length => _elementCount;
+ bool get isEmpty => _elementCount == 0;
+ bool get isNotEmpty => _elementCount != 0;
- /* patch */ Iterable<K> get keys => new _HashMapKeyIterable<K>(this);
- /* patch */ Iterable<V> get values => new _HashMapValueIterable<V>(this);
+ Iterable<K> get keys => new _HashMapKeyIterable<K>(this);
+ Iterable<V> get values => new _HashMapValueIterable<V>(this);
- /* patch */ bool containsKey(Object key) {
+ bool containsKey(Object key) {
int hashCode = key.hashCode;
List buckets = _buckets;
int index = hashCode & (buckets.length - 1);
@@ -31,7 +48,7 @@ patch class HashMap<K, V> {
return false;
}
- /* patch */ bool containsValue(Object value) {
+ bool containsValue(Object value) {
List buckets = _buckets;
int length = buckets.length;
for (int i = 0; i < length; i++) {
@@ -44,7 +61,7 @@ patch class HashMap<K, V> {
return false;
}
- /* patch */ V operator[](Object key) {
+ V operator[](Object key) {
int hashCode = key.hashCode;
List buckets = _buckets;
int index = hashCode & (buckets.length - 1);
@@ -58,7 +75,7 @@ patch class HashMap<K, V> {
return null;
}
- /* patch */ void operator []=(K key, V value) {
+ void operator []=(K key, V value) {
int hashCode = key.hashCode;
List buckets = _buckets;
int length = buckets.length;
@@ -74,7 +91,7 @@ patch class HashMap<K, V> {
_addEntry(buckets, index, length, key, value, hashCode);
}
- /* patch */ V putIfAbsent(K key, V ifAbsent()) {
+ V putIfAbsent(K key, V ifAbsent()) {
int hashCode = key.hashCode;
List buckets = _buckets;
int length = buckets.length;
@@ -96,13 +113,13 @@ patch class HashMap<K, V> {
return value;
}
- /* patch */ void addAll(Map<K, V> other) {
+ void addAll(Map<K, V> other) {
other.forEach((K key, V value) {
this[key] = value;
});
}
- /* patch */ void forEach(void action(K key, V value)) {
+ void forEach(void action(K key, V value)) {
int stamp = _modificationCount;
List buckets = _buckets;
int length = buckets.length;
@@ -118,7 +135,7 @@ patch class HashMap<K, V> {
}
}
- /* patch */ V remove(Object key) {
+ V remove(Object key) {
int hashCode = key.hashCode;
List buckets = _buckets;
int index = hashCode & (buckets.length - 1);
@@ -143,7 +160,7 @@ patch class HashMap<K, V> {
return null;
}
- /* patch */ void clear() {
+ void clear() {
_elementCount = 0;
_buckets = new List(_INITIAL_CAPACITY);
_modificationCount = (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
@@ -182,6 +199,193 @@ patch class HashMap<K, V> {
}
}
+class _CustomHashMap<K, V> extends _HashMapImpl<K, V> {
+ final Function _equals;
+ final Function _hashCode;
+ _CustomHashMap(this._equals, this._hashCode);
+
+ bool containsKey(Object key) {
+ int hashCode = _hashCode(key);
+ List buckets = _buckets;
+ int index = hashCode & (buckets.length - 1);
+ _HashMapEntry entry = buckets[index];
+ while (entry != null) {
+ if (hashCode == entry.hashCode && _equals(entry.key, key)) return true;
+ entry = entry.next;
+ }
+ return false;
+ }
+
+ V operator[](Object key) {
+ int hashCode = _hashCode(key);
+ List buckets = _buckets;
+ int index = hashCode & (buckets.length - 1);
+ _HashMapEntry entry = buckets[index];
+ while (entry != null) {
+ if (hashCode == entry.hashCode && _equals(entry.key, key)) {
+ return entry.value;
+ }
+ entry = entry.next;
+ }
+ return null;
+ }
+
+ void operator []=(K key, V value) {
+ int hashCode = _hashCode(key);
+ List buckets = _buckets;
+ int length = buckets.length;
+ int index = hashCode & (length - 1);
+ _HashMapEntry entry = buckets[index];
+ while (entry != null) {
+ if (hashCode == entry.hashCode && _equals(entry.key, key)) {
+ entry.value = value;
+ return;
+ }
+ entry = entry.next;
+ }
+ _addEntry(buckets, index, length, key, value, hashCode);
+ }
+
+ V putIfAbsent(K key, V ifAbsent()) {
+ int hashCode = _hashCode(key);
+ List buckets = _buckets;
+ int length = buckets.length;
+ int index = hashCode & (length - 1);
+ _HashMapEntry entry = buckets[index];
+ while (entry != null) {
+ if (hashCode == entry.hashCode && _equals(entry.key, key)) {
+ return entry.value;
+ }
+ entry = entry.next;
+ }
+ int stamp = _modificationCount;
+ V value = ifAbsent();
+ if (stamp == _modificationCount) {
+ _addEntry(buckets, index, length, key, value, hashCode);
+ } else {
+ this[key] = value;
+ }
+ return value;
+ }
+
+ V remove(Object key) {
+ int hashCode = _hashCode(key);
+ List buckets = _buckets;
+ int index = hashCode & (buckets.length - 1);
+ _HashMapEntry entry = buckets[index];
+ _HashMapEntry previous = null;
+ while (entry != null) {
+ _HashMapEntry next = entry.next;
+ if (hashCode == entry.hashCode && _equals(entry.key, key)) {
+ if (previous == null) {
+ buckets[index] = next;
+ } else {
+ previous.next = next;
+ }
+ _elementCount--;
+ _modificationCount =
+ (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+ return entry.value;
+ }
+ previous = entry;
+ entry = next;
+ }
+ return null;
+ }
+}
+
+class _IdentityHashMap<K, V> extends _HashMapImpl<K, V> {
+ bool containsKey(Object key) {
+ int hashCode = key.hashCode;
+ List buckets = _buckets;
+ int index = hashCode & (buckets.length - 1);
+ _HashMapEntry entry = buckets[index];
+ while (entry != null) {
+ if (hashCode == entry.hashCode && identical(entry.key, key)) return true;
+ entry = entry.next;
+ }
+ return false;
+ }
+
+ V operator[](Object key) {
+ int hashCode = key.hashCode;
+ List buckets = _buckets;
+ int index = hashCode & (buckets.length - 1);
+ _HashMapEntry entry = buckets[index];
+ while (entry != null) {
+ if (hashCode == entry.hashCode && identical(entry.key, key)) {
+ return entry.value;
+ }
+ entry = entry.next;
+ }
+ return null;
+ }
+
+ void operator []=(K key, V value) {
+ int hashCode = key.hashCode;
+ List buckets = _buckets;
+ int length = buckets.length;
+ int index = hashCode & (length - 1);
+ _HashMapEntry entry = buckets[index];
+ while (entry != null) {
+ if (hashCode == entry.hashCode && identical(entry.key, key)) {
+ entry.value = value;
+ return;
+ }
+ entry = entry.next;
+ }
+ _addEntry(buckets, index, length, key, value, hashCode);
+ }
+
+ V putIfAbsent(K key, V ifAbsent()) {
+ int hashCode = key.hashCode;
+ List buckets = _buckets;
+ int length = buckets.length;
+ int index = hashCode & (length - 1);
+ _HashMapEntry entry = buckets[index];
+ while (entry != null) {
+ if (hashCode == entry.hashCode && identical(entry.key, key)) {
+ return entry.value;
+ }
+ entry = entry.next;
+ }
+ int stamp = _modificationCount;
+ V value = ifAbsent();
+ if (stamp == _modificationCount) {
+ _addEntry(buckets, index, length, key, value, hashCode);
+ } else {
+ this[key] = value;
+ }
+ return value;
+ }
+
+ V remove(Object key) {
+ int hashCode = key.hashCode;
+ List buckets = _buckets;
+ int index = hashCode & (buckets.length - 1);
+ _HashMapEntry entry = buckets[index];
+ _HashMapEntry previous = null;
+ while (entry != null) {
+ _HashMapEntry next = entry.next;
+ if (hashCode == entry.hashCode && identical(entry.key, key)) {
+ if (previous == null) {
+ buckets[index] = next;
+ } else {
+ previous.next = next;
+ }
+ _elementCount--;
+ _modificationCount =
+ (_modificationCount + 1) & _MODIFICATION_COUNT_MASK;
+ return entry.value;
+ }
+ previous = entry;
+ entry = next;
+ }
+ return null;
+ }
+}
+
+
class _HashMapEntry {
final key;
var value;
« no previous file with comments | « no previous file | sdk/lib/_internal/lib/collection_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698