Skip to content

Commit 20be455

Browse files
committed
More HashMap improvements
1 parent 6abd138 commit 20be455

File tree

8 files changed

+55
-44
lines changed

8 files changed

+55
-44
lines changed

convex-core/src/main/java/convex/core/data/AHashMap.java

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package convex.core.data;
22

3-
import java.util.HashSet;
4-
import java.util.Map;
53
import java.util.function.Function;
64
import java.util.function.Predicate;
75

@@ -20,22 +18,22 @@ public AHashMap<K, V> empty() {
2018
return Maps.empty();
2119
}
2220

23-
/**
24-
* Dissoc given a Ref to the key value.
25-
* @param key Ref of key to remove
26-
* @return Map with specified key removed.
27-
*/
28-
public abstract AHashMap<K, V> dissocRef(Ref<K> key);
29-
30-
public abstract AHashMap<K, V> assocRef(Ref<K> keyRef, V value);
31-
3221
@Override
3322
public abstract AHashMap<K, V> assoc(ACell key, ACell value);
23+
24+
public abstract AHashMap<K, V> assocRef(Ref<K> keyRef, V value);
25+
26+
public abstract AHashMap<K, V> assocEntry(MapEntry<K, V> e);
3427

3528
@Override
3629
public abstract AHashMap<K, V> dissoc(ACell key);
37-
38-
public abstract AHashMap<K, V> assocEntry(MapEntry<K, V> e);
30+
31+
/**
32+
* Dissoc given a Hash for the key value.
33+
* @param key Hash of key to remove
34+
* @return Map with specified key removed.
35+
*/
36+
public abstract AHashMap<K, V> dissocHash(Hash key);
3937

4038
/**
4139
* Merge another map into this map. Replaces existing entries if they are
@@ -171,14 +169,6 @@ public AVector<K> getKeys() {
171169
*/
172170
protected abstract Hash getFirstHash();
173171

174-
@Override
175-
public HashSet<Entry<K, V>> entrySet() {
176-
int len = size();
177-
HashSet<Map.Entry<K, V>> h = new HashSet<Map.Entry<K, V>>(len);
178-
accumulateEntrySet(h);
179-
return h;
180-
}
181-
182172
@Override
183173
public AHashMap<K,V> slice(long start) {
184174
return slice(start,count);

convex-core/src/main/java/convex/core/data/AMap.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package convex.core.data;
22

33
import java.util.ArrayList;
4+
import java.util.Collection;
5+
import java.util.HashSet;
46
import java.util.Map;
57
import java.util.Set;
68
import java.util.function.BiConsumer;
@@ -100,11 +102,11 @@ public final boolean containsValue(Object value) {
100102
public abstract MapEntry<K, V> getKeyRefEntry(Ref<ACell> ref);
101103

102104
/**
103-
* Accumulate all entries from this map in the given mutable Set.
105+
* Accumulate all entries from this map in the given collection
104106
*
105107
* @param h HashSet in which to accumulate entries
106108
*/
107-
protected abstract void accumulateEntrySet(Set<Entry<K, V>> h);
109+
protected abstract void accumulateEntries(Collection<Entry<K, V>> h);
108110

109111
/**
110112
* Accumulate all keys from this map in the given mutable Set.
@@ -267,6 +269,14 @@ public Set<K> keySet() {
267269
return ks;
268270
}
269271

272+
@Override
273+
public Set<Entry<K, V>> entrySet() {
274+
int len = size();
275+
HashSet<Map.Entry<K, V>> h = new HashSet<Map.Entry<K, V>>(len);
276+
accumulateEntries(h);
277+
return h;
278+
}
279+
270280
/**
271281
* Gets the map entry with the specified hash
272282
*

convex-core/src/main/java/convex/core/data/ARecord.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package convex.core.data;
22

3+
import java.util.Collection;
34
import java.util.Set;
45
import java.util.function.BiConsumer;
56
import java.util.function.BiFunction;
@@ -153,7 +154,7 @@ public MapEntry<Keyword, ACell> getKeyRefEntry(Ref<ACell> keyRef) {
153154
}
154155

155156
@Override
156-
protected void accumulateEntrySet(Set<Entry<Keyword, ACell>> h) {
157+
protected void accumulateEntries(Collection<Entry<Keyword, ACell>> h) {
157158
for (long i=0; i<count; i++) {
158159
h.add(entryAt(i));
159160
}

convex-core/src/main/java/convex/core/data/Cells.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ public static <T extends ACell> T announce(T a, Consumer<Ref<ACell>> noveltyHand
195195
*/
196196
public static Hash getHash(ACell a) {
197197
if (a==null) return Hash.NULL_HASH;
198-
return a.getHash();
198+
// this picks up a hash in the Ref if available, otherwise populates it for future use
199+
return a.getRef().getHash();
199200
}
200201

201202
public static Blob getEncoding(ACell a) {

convex-core/src/main/java/convex/core/data/Index.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package convex.core.data;
22

3+
import java.util.Collection;
34
import java.util.HashMap;
45
import java.util.Map;
56
import java.util.Set;
@@ -283,9 +284,9 @@ private ABlobLike<?> getPrefix() {
283284
}
284285

285286
@Override
286-
protected void accumulateEntrySet(Set<Entry<K, V>> h) {
287+
protected void accumulateEntries(Collection<Entry<K, V>> h) {
287288
for (int i = 0; i < children.length; i++) {
288-
children[i].getValue().accumulateEntrySet(h);
289+
children[i].getValue().accumulateEntries(h);
289290
}
290291
if (entry != null) h.add(entry);
291292
}

convex-core/src/main/java/convex/core/data/MapLeaf.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.ArrayList;
44
import java.util.Arrays;
5+
import java.util.Collection;
56
import java.util.HashSet;
67
import java.util.Set;
78
import java.util.function.BiConsumer;
@@ -161,10 +162,10 @@ private int seek(K key) {
161162
return -1;
162163
}
163164

164-
private int seekKeyRef(Ref<K> key) {
165+
private int seekKeyRef(Hash keyHash) {
165166
int len = size();
166167
for (int i = 0; i < len; i++) {
167-
if (Utils.equals(key, entries[i].getKeyRef())) return i;
168+
if (Utils.equals(keyHash, entries[i].getKeyHash())) return i;
168169
}
169170
return -1;
170171
}
@@ -178,7 +179,7 @@ public MapLeaf<K, V> dissoc(ACell key) {
178179
}
179180

180181
@Override
181-
public MapLeaf<K, V> dissocRef(Ref<K> key) {
182+
public MapLeaf<K, V> dissocHash(Hash key) {
182183
int i = seekKeyRef(key);
183184
if (i < 0) return this; // not found
184185
return dissocEntry(i);
@@ -300,7 +301,7 @@ protected void accumulateValues(java.util.List<V> al) {
300301
}
301302

302303
@Override
303-
protected void accumulateEntrySet(Set<Entry<K, V>> h) {
304+
protected void accumulateEntries(Collection<Entry<K, V>> h) {
304305
for (int i = 0; i < entries.length; i++) {
305306
MapEntry<K, V> me = entries[i];
306307
h.add(me);

convex-core/src/main/java/convex/core/data/MapTree.java

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package convex.core.data;
22

3+
import java.util.ArrayList;
34
import java.util.Arrays;
5+
import java.util.Collection;
46
import java.util.Comparator;
57
import java.util.HashSet;
68
import java.util.Set;
@@ -289,29 +291,33 @@ protected MapEntry<K, V> getEntryByHash(Hash hash) {
289291
return children[i].getValue().getEntryByHash(hash);
290292
}
291293

292-
@SuppressWarnings("unchecked")
293294
@Override
294295
public AHashMap<K, V> dissoc(ACell key) {
295-
return dissocRef((Ref<K>) Ref.get(key));
296+
return dissocHash(Cells.getHash(key));
296297
}
297298

298299
@Override
299300
@SuppressWarnings("unchecked")
300-
public AHashMap<K, V> dissocRef(Ref<K> keyRef) {
301-
int digit = keyRef.getHash().getHexDigit(shift);
301+
public AHashMap<K, V> dissocHash(Hash keyHash) {
302+
int digit = keyHash.getHexDigit(shift);
302303
int i = Bits.indexForDigit(digit, mask);
303304
if (i < 0) return this; // not present
304305

305306
// dissoc entry from child
306307
AHashMap<K, V> child = children[i].getValue();
307-
AHashMap<K, V> newChild = child.dissocRef(keyRef);
308+
AHashMap<K, V> newChild = child.dissocHash(keyHash);
308309
if (child == newChild) return this; // no removal, no change
309310

310311
if (count - 1 == MapLeaf.MAX_ENTRIES) {
311312
// reduce to a ListMap
312-
HashSet<Entry<K, V>> eset = entrySet();
313-
boolean removed = eset.removeIf(e -> Utils.equals(((MapEntry<K, V>) e).getKeyRef(), keyRef));
314-
if (!removed) throw new Panic("Expected to remove at least one entry!");
313+
ArrayList<Entry<K, V>> eset = new ArrayList<>();
314+
for (int j=0; j<children.length; j++) {
315+
AHashMap<K, V> c = (i==j)?newChild:children[j].getValue();
316+
c.accumulateEntries(eset);
317+
}
318+
if (!(eset.size()==MapLeaf.MAX_ENTRIES)) {
319+
throw new Panic("Expected to remove at least one entry!");
320+
}
315321
return MapLeaf.create(eset.toArray((MapEntry<K, V>[]) MapLeaf.EMPTY_ENTRIES));
316322
} else {
317323
// replace child
@@ -461,9 +467,9 @@ protected void accumulateValues(java.util.List<V> al) {
461467
}
462468

463469
@Override
464-
protected void accumulateEntrySet(Set<Entry<K, V>> h) {
470+
protected void accumulateEntries(Collection<Entry<K, V>> h) {
465471
for (Ref<AHashMap<K, V>> mr : children) {
466-
mr.getValue().accumulateEntrySet(h);
472+
mr.getValue().accumulateEntries(h);
467473
}
468474
}
469475

@@ -839,6 +845,9 @@ public void validate() throws InvalidDataException {
839845
protected void validateWithPrefix(Hash prefix, int shift) throws InvalidDataException {
840846
if (mask == 0) throw new InvalidDataException("TreeMap must have children!", this);
841847
int bsize = children.length;
848+
if (bsize<2) {
849+
throw new InvalidDataException("Non-canonical MapTree with child count "+bsize,this);
850+
}
842851

843852
long childCount=0;;
844853
for (int i = 0; i < bsize; i++) {
@@ -848,7 +857,7 @@ protected void validateWithPrefix(Hash prefix, int shift) throws InvalidDataExce
848857
ACell o = children[i].getValue();
849858
if (!(o instanceof AHashMap)) {
850859
throw new InvalidDataException(
851-
"Expected map child at " + prefix + Utils.toHexChar(digitForIndex(i, mask)), this);
860+
"Expected AHashMap child at " + prefix + Utils.toHexChar(digitForIndex(i, mask)), this);
852861
}
853862
@SuppressWarnings("unchecked")
854863
AHashMap<K, V> child = (AHashMap<K, V>) o;

convex-core/src/test/java/convex/core/data/MapsTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,6 @@ public void testBigMapChild() {
287287

288288
@Test
289289
public void testBigMapSlice() {
290-
291-
292290
AHashMap<CVMLong,CVMLong> bm=Samples.LONG_MAP_100;
293291
AHashMap<CVMLong,CVMLong> bm1=bm.slice(0,18);
294292
assertEquals(18,bm1.count());

0 commit comments

Comments
 (0)