In C++, the STL unordered_map
is an unordered associative container that provides the functionality of an unordered map or dictionary data structure.
In contrast to a regular map, the order of keys in an unordered map is undefined.
Also, the unordered map is implemented as a hash table data structure whereas the regular map is a binary search tree data structure.
Create C++ STL unordered_map
In order to create an unordered map in C++, we first need to include the unordered_map
header file.
#include <unordered_map>
Once we import this file, we can create an unordered map using the following syntax:
unordered_map<key_type, value_type> ump;
Here,
key_type
indicates the data type for the keyvalue_type
indicates the data type for the value
For example,
// create an unordered_map with integer key and value
unordered_map<int, int> ump_integer;
// create an unordered_map with string key and int value
unordered_map<string, int> ump_string;
Initialize an Unordered Map
We can initialize a C++ unordered map in the following ways:
// Initializer List
unordered_map<string, int> unordered_map1 = {
{"One", 1},
{"Two", 2},
{"Three", 3}
};
// Uniform Initialization
unordered_map<string, int> unordered_map2 {
{"One", 1},
{"Two", 2},
{"Three", 3}
};
Here, we have initialized the unordered map by providing values directly to them.
Now, both unordered_map1 and unordered_map2 are initialized with {{"One", 1}, {"Two", 2}, {"Three", 3}}
.
Example: C++ unordered_map
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
// uniform initialization
unordered_map<string, int> unordered_map1 {
{"One", 1},
{"Two", 2},
{"Three", 3}
};
cout << "Key - Value" << endl;
// loop across the unordered map
// display the key-value pairs
for(const auto& key_value: unordered_map1) {
string key = key_value.first;
int value = key_value.second;
cout << key << " - " << value << endl;
}
return 0;
}
Output
Key - Value Three - 3 Two - 2 One - 1
In the above example, we have declared and initialized an unordered map named unordered_map1 using uniform initialization.
unordered_map<string, int> unordered_map1 {
{"One", 1},
{"Two", 2},
{"Three", 3}
};
Then, we have displayed the unordered map content using a ranged for loop.
for(const auto& key_value: unordered_map1) {
string key = key_value.first;
int value = key_value.second;
cout << key << " - " << value << endl;
}
In the above code, each element (key-value pair) of the unordered map is stored in variable key_value.
Then, we get the key and value using:
key_value.first
- gives the keykey_value.second
- gives the value
Notice that we have created the unordered map in order of the keys: "One"
, "Two"
, "Three"
. However, the output is in undefined order.
This is because the elements are not stored in any particular order based on key, or the values.
Note: Starting from C++17, you can use structure bindings to simplify this code further:
for(const auto& [key, value]: unordered_map1) {
cout << key << " - " << value << endl;
}
Other Ways to Initialize a C++ Unordered Map
We can copy one unordered map to another using range method initialization.
unordered_map<string, int> unordered_map_1 {
{"One", 1},
{"Two", 2},
{"Three", 3}
};
unordered_map<string, int> unordered_map_2(unordered_map_1.begin(), unordered_map_1.end());
Here, we have first created an unordered map named unordered_map_1. Then, we created another unordered map called unordered_map_2 by copying all the elements of unordered_map_1.
C++ Unordered Map Methods
In C++, the unordered_map
class provides various methods to perform different operations on an unordered map.
Methods | Description |
---|---|
insert() |
insert one or more key-value pairs |
count() |
returns 1 if key exists and 0 if not |
find() |
returns the iterator to the element with the specified key |
at() |
returns the element at the specified key |
size() |
returns the number of elements |
empty() |
returns true if the unordered map is empty |
erase() |
removes elements with specified key |
clear() |
removes all elements |
Insert Key-Value Pairs to an Unordered Map
We can insert a key-value pair in an unordered map using :
insert()
- insert key-value pairs[]
- insert a key and value
For example,
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
unordered_map<string, int> unordered_map1;
// insert key-value pair {"One", 1}
unordered_map1["One"] = 1;
// insert a pair {"Two", 2}
unordered_map1.insert({"Two", 2});
// insert two pairs {"Three", 3}, {"Four", 4}
unordered_map1.insert({{"Three", 3}, {"Four", 4}});
cout << "Key - Value" << endl;
// display elements of unordered_map1
for(const auto& key_value: unordered_map1) {
string key = key_value.first;
int value = key_value.second;
cout << key << " - " << value << endl;
}
return 0;
}
Output
Key - Value Four - 4 Two - 2 Three - 3 One - 1
In the above example, we have initialized an empty unordered map to store the key-value pairs of a string and an integer.
Then, we have inserted the pair {"One", 1}
using []
.
unordered_map1["One"] = 1;
We have then inserted another pair using the insert()
method.
unordered_map1.insert({"Two", 2});
Finally, we inserted two pairs using insert()
.
unordered_map1.insert({{"Three", 3}, {"Four", 4}});
Access Values of Unordered Maps
We can use the following methods to access the values of the specified key of an unordered map:
at()
- returns value for the specified key[]
- returns value for the specified key
For example,
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
unordered_map<string, string> capital_city {
{"Nepal", "Kathmandu"},
{"India", "New Delhi"},
{"Australia", "Canberra"}
};
cout << "Capital of Nepal is " << capital_city["Nepal"] << endl;
cout << "Capital of Australia is " << capital_city.at("Australia");
return 0;
}
Output
Capital of Nepal is Kathmandu Capital of Australia is Canberra
In the above example,
capital_city["Nepal"]
- returns the element with key"Nepal"
capital_city.at("Australia")
- returns the element with key"Australia"
Note: While we can use the []
operator to access the elements, it is preferable to use the at()
method.
This is because at()
throws an exception whenever the specified key doesn't exist, while []
pairs the key with a garbage value.
For example,
// key "Japan" doesn't exist
// so the key "Japan" is paired with a garbage value
cout << "Capital of Japan is: " << capital_city["Japan"];
Change Values of an Unordered Map
We can use the at()
method or the []
operator to change the value of the unordered map. For example,
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
unordered_map<string, string> capital_city {
{"India", "Calcutta"},
{"Pakistan", "Karachi"},
};
cout << "Old Capitals:" << endl;
cout << "India : " << capital_city["India"] << endl;
cout << "Pakistan : " << capital_city["Pakistan"];
// change value for "India" using []
capital_city["India"] = "New Delhi";
// change value for "Pakistan" using at()
capital_city.at("Pakistan") = "Islamabad";
cout << "\n\nNew Capitals:" << endl;
cout << "India : " << capital_city["India"] << endl;
cout << "Pakistan : " << capital_city["Pakistan"];
return 0;
}
Output
Old Capitals: India : Calcutta Pakistan : Karachi New Capitals: India : New Delhi Pakistan : Islamabad
In the above example, the initial key-value pairs for capital_city are {"India", "Calcutta"}
and {"Pakistan", "Karachi"}
.
Then, we have used the []
operator to change the value for key "India"
using:
capital_city["India"] = "New Delhi";
Similarly, we have used the at()
method to change the value for the key "Pakistan"
using:
capital_city.at("Pakistan") = "Islamabad";
Remove Elements From an Unordered Map
We can remove the element with the specified key of an unordered map using the erase()
method. For example,
#include <iostream>
#include <unordered_map>
using namespace std;
// function prototype for display_unordered_map()
void display_unordered_map(const unordered_map<int, string> &);
int main() {
unordered_map<int, string> student {
{111, "John"},
{132, "Mark"},
{143, "Chris"}
};
cout << "Initial Unordered Map:\n";
display_unordered_map(student);
// remove element with key: 143
student.erase(143);
cout << "\nFinal Unordered Map: \n";
display_unordered_map(student);
return 0;
}
// utility function to print unordered_map elements
void display_unordered_map(const unordered_map<int, string> &umap){
for(const auto& key_value: umap) {
int key = key_value.first;
string value = key_value.second;
cout << key << " - " << value << endl;
}
}
Output
Initial Unordered Map: 143 - Chris 132 - Mark 111 - John Final Unordered Map: 132 - Mark 111 - John
In the above example, we have used the erase()
method to remove an element from the unordered map.
Initially, the content of unordered map named student is {{"143": Chris}, {"132": Mark}, {"111": John}}
.
Then we have used the erase()
method to remove the element with key 143.
// removes element with the key 143
student.erase(143);
So the final content becomes {{"132": Mark}, {"111": John}}
.
Note: We can use the clear()
method to remove all the elements of the unordered map.
Check if a Key Exists in the Unordered Map
We can use the following methods to check if the specified key exists in the unordered map.
find()
- returns the iterator to the element if the key is found, else returns theend()
iteratorcount()
- returns 1 if the key exists and 0 if not
For example,
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
unordered_map<int, string> student{
{111, "John"},
{132, "Mark"},
{143, "Chris"}
};
cout << "Using find():" << endl;
cout << "Does id " << 143 << " exist? ";
// find() returns student.end() if the key is not found
if (student.find(143) != student.end()) {
cout << "Yes";
}
else {
cout << "No";
}
cout << "\n\nUsing count():" << endl;
cout << "Does id " << 1433 << " exist? ";
// count() returns 0 if the key doesn't exist
if (student.count(1433)) {
cout << "Yes";
}
else {
cout << "No";
}
return 0;
}
Output
Using find(): Does id 143 exist? Yes Using count(): Does id 1433 exist? No
In the above example, we have used find()
and count()
to check if a given key exists in the unordered map.
Initially, we have used the find()
method to check if the key 143 exists.
// checks if key 143 exists
if (student.find(143) != student.end()) {
cout << "Yes";
}
else {
cout << "No";
}
The find()
method returns an iterator pointing to the element if it exists. If the key doesn't exist, it points to the end()
iterator.
Then, we have used the count()
method to check if the key 1433 exists.
// checks if key 1433 exists
if (student.count(1433)) {
cout << "Yes";
}
else {
cout << "No";
}