lib: update HashMap and ArrayMap to support nullable keys
authorAlexis Laferrière <alexis.laf@xymus.net>
Thu, 18 Dec 2014 15:30:38 +0000 (10:30 -0500)
committerAlexis Laferrière <alexis.laf@xymus.net>
Tue, 13 Jan 2015 19:09:54 +0000 (14:09 -0500)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

lib/standard/collection/array.nit
lib/standard/collection/hash_collection.nit

index 68f84e7..44ea5d3 100644 (file)
@@ -536,7 +536,7 @@ end
 
 
 # Associative arrays implemented with an array of (key, value) pairs.
-class ArrayMap[K: Object, E]
+class ArrayMap[K, E]
        super CoupleMap[K, E]
 
        # O(n)
@@ -618,7 +618,7 @@ class ArrayMap[K: Object, E]
        end
 end
 
-private class ArrayMapKeys[K: Object, E]
+private class ArrayMapKeys[K, E]
        super RemovableCollection[K]
        # The original map
        var map: ArrayMap[K, E]
@@ -638,7 +638,7 @@ private class ArrayMapKeys[K: Object, E]
        redef fun remove_all(key) do self.remove(key)
 end
 
-private class ArrayMapValues[K: Object, E]
+private class ArrayMapValues[K, E]
        super RemovableCollection[E]
        # The original map
        var map: ArrayMap[K, E]
index d389c5a..cae46fd 100644 (file)
@@ -16,7 +16,7 @@ module hash_collection
 import array
 
 # A HashCollection is an array of HashNode[K] indexed by the K hash value
-private abstract class HashCollection[K: Object]
+private abstract class HashCollection[K]
        type N: HashNode[K]
 
        var array: nullable NativeArray[nullable N] = null # Used to store items
@@ -35,12 +35,14 @@ private abstract class HashCollection[K: Object]
        # Return the index of the key k
        fun index_at(k: K): Int
        do
+               if k == null then return 0
+
                var i = k.hash % _capacity
                if i < 0 then i = - i
                return i
        end
 
-       # Return the node assosiated with the key
+       # Return the node associated with the key
        fun node_at(k: K): nullable N
        do
                # cache: `is` is used instead of `==` because it is a faster filter (even if not exact)
@@ -52,7 +54,7 @@ private abstract class HashCollection[K: Object]
                return res
        end
 
-       # Return the node assosiated with the key (but with the index already known)
+       # Return the node associated with the key (but with the index already known)
        fun node_at_idx(i: Int, k: K): nullable N
        do
                var c = _array[i]
@@ -190,7 +192,7 @@ private abstract class HashCollection[K: Object]
        end
 end
 
-private abstract class HashNode[K: Object]
+private abstract class HashNode[K]
        var key: K
        type N: HashNode[K]
        var next_item: nullable N = null
@@ -199,9 +201,20 @@ private abstract class HashNode[K: Object]
        var next_in_bucklet: nullable N = null
 end
 
-# A map implemented with a hash table.
-# Keys of such a map cannot be null and require a working `hash` method
-class HashMap[K: Object, V]
+# A `Map` implemented with a hash table.
+#
+# ~~~
+# var map = new HashMap[nullable String, Int]
+# map[null] = 0
+# map["one"] = 1
+# map["two"] = 2
+#
+# assert map[null] == 0
+# assert map["one"] == 1
+# assert map.keys.has("two")
+# assert map.values.length == 3
+# ~~~
+class HashMap[K, V]
        super Map[K, V]
        super HashCollection[K]
 
@@ -249,7 +262,7 @@ class HashMap[K: Object, V]
 end
 
 # View of the keys of a HashMap
-private class HashMapKeys[K: Object, V]
+private class HashMapKeys[K, V]
        super RemovableCollection[K]
        # The original map
        var map: HashMap[K, V]
@@ -270,7 +283,7 @@ private class HashMapKeys[K: Object, V]
 end
 
 # View of the values of a Map
-private class HashMapValues[K: Object, V]
+private class HashMapValues[K, V]
        super RemovableCollection[V]
        # The original map
        var map: HashMap[K, V]
@@ -340,14 +353,14 @@ private class HashMapValues[K: Object, V]
        end
 end
 
-private class HashMapNode[K: Object, V]
+private class HashMapNode[K, V]
        super HashNode[K]
        redef type N: HashMapNode[K, V]
        var value: V
 end
 
 # A `MapIterator` over a `HashMap`.
-class HashMapIterator[K: Object, V]
+class HashMapIterator[K, V]
        super MapIterator[K, V]
        redef fun is_ok do return _node != null