I need at least the first commit since MapIterators can be used with non-maps. The second commit is more for consistency. Note that HashMap keys are still non-null.
If this is of interest to you, I'll complete and publish my `NullableMap` in `more_collection`.
Pull-Request: #1041
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Jean Privat <jean@pryen.org>
# assert m.has_key("four")
# assert m["four"] == ['i', 'i', 'i', 'i']
# assert m["zzz"] == new Array[Char]
-class MultiHashMap[K: Object, V]
+class MultiHashMap[K, V]
super HashMap[K, Array[V]]
# Add `v` to the array associated with `k`.
# assert hm2[1, "one"] == 1.0
# assert hm2[2, "not-two"] == null
# ~~~~
-class HashMap2[K1: Object, K2: Object, V]
+class HashMap2[K1, K2, V]
private var level1 = new HashMap[K1, HashMap[K2, V]]
# Return the value associated to the keys `k1` and `k2`.
# assert hm3[1, "one", 11] == 1.0
# assert hm3[2, "not-two", 22] == null
# ~~~~
-class HashMap3[K1: Object, K2: Object, K3: Object, V]
+class HashMap3[K1, K2, K3, V]
private var level1 = new HashMap[K1, HashMap2[K2, K3, V]]
# Return the value associated to the keys `k1`, `k2`, and `k3`.
# assert dma["b"] == [65, 66]
# assert dma.default == [65]
# ~~~~
-class DefaultMap[K: Object, V]
+class DefaultMap[K, V]
super HashMap[K, V]
# The default value.
end
# MapRead are abstract associative collections: `key` -> `item`.
-interface MapRead[K: Object, V]
+interface MapRead[K, V]
# Get the item at `key`
#
# var x = new HashMap[String, Int]
# assert map.values.has(1) == true
# assert map.values.has(3) == false
#
-interface Map[K: Object, V]
+interface Map[K, V]
super MapRead[K, V]
# Set the `value` at `key`.
end
# Iterators for Map.
-interface MapIterator[K: Object, V]
+interface MapIterator[K, V]
# The current item.
# Require `is_ok`.
fun item: V is abstract
end
# Iterator on a 'keys' point of view of a map
-class MapKeysIterator[K: Object, V]
+class MapKeysIterator[K, V]
super Iterator[K]
# The original iterator
var original_iterator: MapIterator[K, V]
end
# Iterator on a 'values' point of view of a map
-class MapValuesIterator[K: Object, V]
+class MapValuesIterator[K, V]
super Iterator[V]
# The original iterator
var original_iterator: MapIterator[K, V]
# Associative arrays that internally uses couples to represent each (key, value) pairs.
# This is an helper class that some specific implementation of Map may implements.
-interface CoupleMap[K: Object, V]
+interface CoupleMap[K, V]
super Map[K, V]
# Return the couple of the corresponding key
# Iterator on CoupleMap
#
# Actually it is a wrapper around an iterator of the internal array of the map.
-private class CoupleMapIterator[K: Object, V]
+private class CoupleMapIterator[K, V]
super MapIterator[K, V]
redef fun item do return _iter.item.second
# 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)
end
end
-private class ArrayMapKeys[K: Object, E]
+private class ArrayMapKeys[K, E]
super RemovableCollection[K]
# The original map
var map: ArrayMap[K, 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]
# You are allowed to redistribute it and sell it, alone or is a part of
# another product.
-# Introduce Hashmap and Hashset.
+# Introduce `HashMap` and `HashSet`.
module hash_collection
import array
+redef class Map[K, V]
+ # Get a `HashMap[K, V]` as default implementation
+ new do return new HashMap[K, V]
+end
+
# 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
# 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)
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]
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
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]
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]
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]
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
var i = iterator
var k = i.key
var e = i.item
- s.append("{k}{couple_sep}{e or else "<null>"}")
+ s.append("{k or else "<null>"}{couple_sep}{e or else "<null>"}")
# Concat other items
i.next
s.append(sep)
k = i.key
e = i.item
- s.append("{k}{couple_sep}{e or else "<null>"}")
+ s.append("{k or else "<null>"}{couple_sep}{e or else "<null>"}")
i.next
end
return s.to_s
is_col = true
end
- if mapit_cla != null and v.is_subtype(ittype, mapit_cla.get_mtype([objcla.mclass_type, objcla.mclass_type.as_nullable])) then
+ if mapit_cla != null and v.is_subtype(ittype, mapit_cla.get_mtype([objcla.mclass_type.as_nullable, objcla.mclass_type.as_nullable])) then
# Map Iterator
var coltype = ittype.supertype_to(v.mmodule, v.anchor, mapit_cla)
var variables = self.variables