OLD | NEW |
---|---|
(Empty) | |
1 part of dart.collection; | |
2 | |
3 class HashMap<K, V> extends _HashTable<K> implements Map<K, V> { | |
4 static const int _INITIAL_CAPACITY = 8; | |
5 static const int _VALUE_INDEX = 1; | |
6 | |
7 HashMap() : super(_INITIAL_CAPACITY); | |
8 | |
9 factory HashMap.from(Map<K, V> other) { | |
10 return new HashMap<K, V>()..addAll(other); | |
11 } | |
12 | |
13 int get _entrySize => 2; | |
14 | |
15 V _value(int offset) => _table[offset + _VALUE_INDEX]; | |
16 void _setValue(int offset, V value) { _table[offset + _VALUE_INDEX] = value; } | |
17 | |
18 _copyEntry(List fromTable, int fromOffset, int toOffset) { | |
floitsch
2013/02/06 10:43:58
Add comment that this is just to be more efficient
Lasse Reichstein Nielsen
2013/02/08 13:53:01
Base function has been reduced to not copying anyt
| |
19 _setValue(toOffset, fromTable[fromOffset + _VALUE_INDEX]); | |
floitsch
2013/02/06 10:43:58
Don't use '_setValue' it makes it confusing.
_tabl
Lasse Reichstein Nielsen
2013/02/08 13:53:01
Done.
| |
20 } | |
21 | |
22 bool containsKey(K key) { | |
23 return _get(key) >= 0; | |
24 } | |
25 | |
26 bool containsValue(V value) { | |
27 for (int offset = 0; offset < _table.length; offset += _entrySize) { | |
28 if (!_isFree(_table[offset]) && _value(offset) == value) { | |
29 return true; | |
30 } | |
31 } | |
32 return false; | |
33 } | |
34 | |
35 void addAll(Map<K, V> other) { | |
36 _ensureCapacity(other.length); | |
37 other.forEach((K key, V value) { | |
38 int offset = _put(key); | |
39 _setValue(offset, value); | |
40 _modificationCount++; | |
erikcorry
2013/02/05 16:25:05
You probably want to mask this with something so i
Lasse Reichstein Nielsen
2013/02/05 19:47:40
That could be wrong, if you keep an iterator alive
floitsch
2013/02/06 10:43:58
It's 30 bits (1 for tagging, 1 for the sign). That
Lasse Reichstein Nielsen
2013/02/08 13:53:01
Done.
| |
41 }); | |
42 } | |
43 | |
44 V operator [](K key) { | |
45 int offset = _get(key); | |
46 if (offset >= 0) return _value(offset); | |
47 return null; | |
48 } | |
49 | |
50 void operator []=(K key, V value) { | |
51 _ensureCapacity(1); | |
52 int offset = _put(key); | |
53 _setValue(offset, value); | |
erikcorry
2013/02/05 16:25:05
Seems inconsistent that you don't increment the mo
Lasse Reichstein Nielsen
2013/02/05 19:47:40
The modification count is only for modifications t
erikcorry
2013/02/06 10:57:56
You already called _ensureCapacity, which may have
floitsch
2013/02/06 11:45:46
I would not make it dependent on the actual outcom
Lasse Reichstein Nielsen
2013/02/08 13:53:01
I prefer to consider only operations that change t
erikcorry
2013/02/11 10:18:29
If that is the contract with the user, then you ne
Lasse Reichstein Nielsen
2013/02/11 14:07:37
Gah!
Ok. I think I can do something for non-linke
erikcorry
2013/02/11 14:42:05
So if you update the values for preexisting keys w
Lasse Reichstein Nielsen
2013/02/12 10:34:47
Yes, That's acceptable. You always get the element
| |
54 } | |
55 | |
56 V putIfAbsent(K key, V ifAbsent()) { | |
57 _ensureCapacity(1); | |
58 int offset = _probeForAdd(_hashCodeOf(key), key); | |
59 Object prevKey = _key(offset); | |
60 if (_isFree(prevKey)) { | |
61 V value = ifAbsent(); | |
62 _setKey(offset, key); | |
63 _setValue(offset, value); | |
64 if (prevKey == null) { | |
65 _entryCount++; | |
66 } else { | |
67 assert(identical(prevKey, _TOMBSTONE)); | |
68 _deletedCount--; | |
69 } | |
70 _modificationCount++; | |
71 return value; | |
72 } | |
73 return _value(offset); | |
74 } | |
75 | |
76 V remove(K key) { | |
77 int offset = _remove(key); | |
78 if (offset < 0) return null; | |
79 V oldValue = _value(offset); | |
80 _setValue(offset, null); | |
81 return oldValue; | |
82 } | |
83 | |
84 void clear() { | |
85 _clear(); | |
86 } | |
87 | |
88 void forEach(void action (K key, V value)) { | |
89 int modCount = _modificationCount; | |
90 for (int offset = 0; offset < _table.length; offset += 2) { | |
erikcorry
2013/02/05 16:25:05
+= _entrySize?
Lasse Reichstein Nielsen
2013/02/05 19:47:40
Yes, it's probably more readable, even if we know
| |
91 if (modCount != _modificationCount) { | |
92 throw new ConcurrentModificationError(this); | |
93 } | |
94 Object entry = _key(offset); | |
95 if (!_isFree(entry)) { | |
96 K key = entry; | |
97 V value = _value(offset); | |
98 action(key, value); | |
99 } | |
100 } | |
101 } | |
102 | |
103 Iterable<K> get keys => new _HashTableKeyIterable<K>(this); | |
104 Iterable<V> get values => | |
105 new _HashTableValueIterable<V>(this, _VALUE_INDEX); | |
106 | |
107 int get length => _elementCount; | |
108 | |
109 bool get isEmpty => _elementCount == 0; | |
110 | |
111 String toString() => Maps.mapToString(this); | |
112 } | |
OLD | NEW |