A HashMap is a templated data structure that can map unique keys of type A to values of type B (where A and B can be the same type).
Declaration
NOTE: The types HashMap
and KeyValue
not currently appear in the nada_base_types list and does not currently show up in code completion suggestions (T552) during initial declaration.
HashMap declaration is similiar to the declaration of any templated type in Nada. When a HashMap is created, by default, it has no elements.
var namesToObjects = HashMap[String, Cog]();
var idToCost = HashMap[Integer, Real]();
var spawnerToEnemyType = HashMap[Cog, Archetype]();
var enemyType = HashMap[Archetype, Integer]();
HashMaps have a variety of uses. One may use them to keep track of objects at runtime by an alternate name, or to keep count of how many of each enemy archetype a spawner has created at runtime. Below are some simple example of HashMap functionality which map unique integer keys to non-unique string values.
Initialization
It is common for a HashMap to be populated at runtime, but it is also possible to define elements within an initializer list.
var hash = HashMap[Integer, String]()
{
{1, "one"},
{2, "two"},
{3, "three"}
};
this.PrintHashMap(hash);
HashMap[Integer, String] (20744110)
{
{2, two}
{1, one}
{3, three}
}
Notice that the order in which the elements are printed is not the order in which they were added to the HashMap. This is due to HashMaps having no inherent order, unlike Arrays. Instead of the pairs being printed in an indexed order they are printed in an arbitrary order based on the hash of the pair.
NOTE: The HashMap templated type is currently lacking templated print functionality similiar to Arrays. The PrintHashMap
function used in this page is implemented below:
function PrintHashMap(hash : HashMap[Integer, String])
{
Console.WriteLine("`hash` \n{");
foreach(var pair in hash.All)
{
Console.WriteLine(" {`pair.Key`, `pair.Value`}");
}
Console.WriteLine("}");
}
HashMap Access
HashMap elements can be accessed for reading or writing in a few different ways which have different primary use cases.
The []
Operator
The []
(pronounced subscript) operator is the primary way to access any value// within a HashMap. When a valid //key is passed to the subscript operator the corresponding value is returned from the HashMap. The []
operator can also be used to assign new values to keys within the HashMap.
var hash = HashMap[Integer, String]()
{
{1, "one"},
{2, "two"}
};
hash[3] = "three";
Console.WriteLine(hash[1]);
Console.WriteLine(hash[2]);
Console.WriteLine(hash[3]);
one
two
three
IMPORTANT: If an invalid key is passed to the []
operator a runtime exception will be thrown:
Get Functions
Another way to access the KeyValue
pairs of a HashMap is to use the get
functions.
HashMap.Get
HashMap.Get
behaves the same as the []
operator, as it is the function actually called by the []
operator. However, being a function, Get
can be referenced by a delegate.
var hash = HashMap[Integer, String]()
{
{1, "one"},
{2, "two"},
{3, "three"}
};
Console.WriteLine(hash.Get(1));
Console.WriteLine(hash.Get(2));
Console.WriteLine(hash.Get(3));
one
two
three
HashMap.GetOrDefault
HashMap.GetOrDefault
behaves the same as Get, but instead of throwing an exception when passed an invalid key it returns a default// value that is the same type as the //values of the HashMap.
var hash = HashMap[Integer, String]()
{
{1, "one"},
{2, "two"},
{3, "three"}
};
Console.WriteLine(hash.GetOrDefault(1, "default"));
Console.WriteLine(hash.GetOrDefault(2, "default"));
Console.WriteLine(hash.GetOrDefault(3, "default"));
Console.WriteLine(hash.GetOrDefault(4, "default"));
Console.WriteLine(hash.GetOrDefault(5));
one
two
three
default
(null) String
HashMap.GetOrError
GetOrError
has the same functionality as Get, the only difference being that it is not called by the []
operator.
Adding to a HashMap
There are multiple ways to add KeyValue
pairs to HashMaps. Add, Set, and the []
operator can all be used to add KeyValue
pairs to the HashMap.
HashMap.Add
Add
takes a key and //value//, adding the pair to the HashMap. If the given key already exists then a runtime exception will be thrown.
var hash = HashMap[Integer, String]();
hash.Add(1, "one");
hash.Add(2, "two");
hash.Add(3, "three");
this.PrintHashMap(hash);
HashMap[Integer, String] (20744110)
{
{2, two}
{1, one}
{3, three}
}
It should be noted that the Add
function is called for each KeyValue
pair when a HashMap is populated using an initializer list.
HashMap.Set
Set
is very similar to Add. Set
takes a key// and //value//, adding the pair to the HashMap if the key does not exist. If the key does exist then the //value paired with the given key will be replaced with the //given value//.
var hash = HashMap[Integer, String]();
hash.Set(1, "one");
hash.Set(2, "two");
hash.Set(2, "three");
this.PrintHashMap(hash);
HashMap[Integer, String] (20744110)
{
{2, three}
{1, one}
}
HashMap.SetOrOverwrite
The relationship of Set and SetOrOverwrite
is simliar to that of Get and GetOrError in that they have the same behavior. However, like Get, Set is called by the []
operator during assignment.
var hash = HashMap[Integer, String]();
hash.SetOrOverwrite(1, "one");
hash.SetOrOverwrite(2, "two");
hash.SetOrOverwrite(2, "three");
this.PrintHashMap(hash);
HashMap[Integer, String] (20744110)
{
{2, three}
{1, one}
}
HashMap.SetOrIgnore
SetOrIgnore
behaves the same as Set except if the given key already exists the function returns leaving the HashMap unmodified.
var hash = HashMap[Integer, String]();
hash.SetOrIgnore(1, "one");
hash.SetOrIgnore(2, "two");
hash.SetOrIgnore(2, "three");
this.PrintHashMap(hash);
HashMap[Integer, String] (20744110)
{
{2, two}
{1, one}
}
HashMap.SetOrError
SetOrError
follows a similiar behavior to GetOrError. If the key passed to SetOrError
already exists in the HashMap then an exception will be thrown.
HashMap Container Operations
HashMap.Clear
The Clear
function simply removes all KeyValue
pairs from the HashMap.
var hash = HashMap[Integer, String]();
hash[1] = "one";
hash[2] = "two";
hash[3] = "three";
this.PrintHashMap(hash);
hash.Clear();
this.PrintHashMap(hash);
HashMap[Integer, String] (20712538)
{
{2, two}
{1, one}
{3, three}
}
HashMap[Integer, String] (20712538)
{
}
HashMap.Contains
Contains
takes a parameter matching the key type of the HashMap and returns true
if the given key exists in the HashMap.
var hash = HashMap[Integer, String]();
hash[1] = "one";
hash[2] = "two";
hash[3] = "three";
this.PrintHashMap(hash);
Console.WriteLine("This HashMap contains the key 2: `hash.Contains(2)`");
Console.WriteLine("This HashMap contains the key 4: `hash.Contains(4)`");
HashMap[Integer, String] (20713030)
{
{2, two}
{1, one}
{3, three}
}
This HashMap contains the key 2: true
This HashMap contains the key 4: false
HashMap Range Functions
There are a number of HashMap properties providing iterable ranges that are particularly useful for examining each pair in a HashMap.
HashMap.All
Contains an iterable range of all KeyValue
pairs in the HashMap.
function PrintHashMap(hash : HashMap[Integer, String])
{
Console.WriteLine("`hash` \n{");
foreach(var pair in hash.All)
{
Console.WriteLine(" {`pair.Key`, `pair.Value`}");
}
Console.WriteLine("}");
}
The PrintHashMap
function is an excellent example of how one may use All
.
HashMap.Keys & HashMap.Values
Keys
and Values
return iterable ranges of containing the keys and values in the HashMap correspondingly.
HashMap.Count
Count
returns the number of pairs in the HashMap.
Related Materials
Manual
Reference
Task
- T1317