unordered_map usage details

Posted by zephyrstudios on Fri, 04 Feb 2022 13:31:46 +0100

STL: unordered_map usage notes

Reference website:

1. General

unordered_ The template of map is defined as follows:

template < class Key,                                    // unordered_map::key_type
           class T,                                      // unordered_map::mapped_type
           class Hash = hash<Key>,                       // unordered_map::hasher
           class Pred = equal_to<Key>,                   // unordered_map::key_equal
           class Alloc = allocator< pair<const Key,T> >  // unordered_map::allocator_type
           > class unordered_map;

unordered_map is an association container that stores elements based on key value and mapping, namely key value. Allows you to quickly find elements based on keys. In unordered_ In the map, the key value uniquely identifies the element, and the mapped value is an object of the content associated with the object.

For order and disorder:

  • unordered_ The disorder of map is reflected in that the internal storage structure is hash table, so that the elements can be accessed quickly through key values.
  • The corresponding ordered associated container is map. The order of map is reflected in the internal storage structure of red black tree. During storage, the elements are automatically arranged in the order from small to large.

The internal storage structure also determines unordered_map and map differ in some features:

  • Search efficiency
    • unordered_map search efficiency is higher, which can reach O(1), but the range iteration efficiency of element subset is low.
    • For map, according to the traversal order of middle order traversal, it is convenient to iterate to get the elements from small to large

Unordered mapping implements the direct access operator (operator []), which allows direct access to mapped values using their key values as parameters. Iterators in containers are at least forward iterators forward iterators.

2. Properties

2.1 relevance

The elements in the associated container are referenced by their keys, not by their absolute position in the container.

2.2 disorder

Unordered containers use hash tables to organize their elements, which allow quick access to elements through their keys.

2.3 Map mapping

Each element associates a key with a mapping value: a key means identifying the element whose main content is the mapping value.

2.4 uniqueness of key

No two elements in the container have the same key

2.5 Allocator-aware

The container uses an allocator object to dynamically handle its storage requirements.

3. Template parameters

template < class Key,                                    // unordered_map::key_type
           class T,                                      // unordered_map::mapped_type
           class Hash = hash<Key>,                       // unordered_map::hasher
           class Pred = equal_to<Key>,                   // unordered_map::key_equal
           class Alloc = allocator< pair<const Key,T> >  // unordered_map::allocator_type
           > class unordered_map;
  • key

    Type of key value. unordered_ Each element in the map is uniquely identified by its key value.

  • T

    Type of mapping value. unordered_ Each element in the map is used to store some data as its mapping value.

  • Hash

    A unary function object type that accepts an object of type key as a parameter and returns size based on the object_ Unique value of type T. This can be a class that implements a function call operator or a pointer to a function (see constructor). The default is hash < key >.

  • Pred

    Accepts two key type parameters and returns a binary predicate of type bool. Expression PRED (a, b). PRED is an object of this type. A and B are key values and return true. If yes, it should be considered equivalent to B. This can be a class that implements a function call operator or a pointer to a function (see constructor as an example). This defaults to equal_ To < key >, which returns the same result as applying the equality operator (a==b).

  • Allloc

    The type of allocator object used to define the storage allocation model. By default, the allocator class template is used, which defines the simplest memory allocation model and is independent of values.

4. Member function

4.1 constructor and initialization

(1) The default constructor of the template class, creating an empty unordered_map

unordered_map<int, string> umap;

(2) Initialize with initialization list

unordered_map<int, string> umap = unordered_map<int, string>({{1,"a"},{2,"b"}});  // Explicitly call C + + constructor
unordered_map<int, string> umap2({{3,"c"},{4,"d"}});	// Implicit call constructor, more concise
unordered_map<string, string> umap{
    {"TaoBao","https://www.taobao.com/"},
    {"JD.COM","https://www.jd.com/"},
    {"Tmall mall","https://jx.tmall.com/"} };

(3) Copy constructor initialization

// copy constructor  
unordered_map<int, string> umap4(umap3);

(4) Iterator initialization

// range
unordered_map<int, string> umap5(umap1.begin(), umap1.end());

(5) Copy initialization

typedef std::unordered_map<std::string,std::string> stringmap;
first = {{"AAPL","Apple"},{"MSFT","Microsoft"}};  // init list
second = {{"GOOG","Google"},{"ORCL","Oracle"}};   // init list
third = merge(first,second);                      // move
first = third;                                    // copy	

4.2 capacity

(1) Is it empty

cout << "first " << (first.empty() ? "is empty" : "is not empty") << endl;
cout << "first " << (second.empty() ? "is empty" : "is not empty") << endl;

(2) Current capacity

cout << "thrid.size is" << third.size() << endl;

4.3 iteration

/**  Iteration **/
for (auto it = first.begin(); it != first.end(); it++){
    cout << " " << it->first << ":" << it->second;
}
cout<<endl;

4.4 access to elements

(1)operator[]

first["GOOG"] = "Google";		// new element inserted
first["AAPL"] = "Apple";		// new element inserted
first["MSFT"] = "Microsoft";	// new element inserted
first["BOB"] = "Bob";
string brand1 = first["GOOG"];	// read
first["BOB"] = "";				// writen
for (auto it = first.begin(); it != first.end(); it++){
    cout << " " << it->first << ":" << it->second;
}
cout<<endl;

(2)at

unrdered_map<string,int> mymap = {
    {"Mars", 3000},
    {"Saturn", 60000},
    {"Jupiter", 70000}};
mymap.at("Mars") = 3396;
mymap.at("Saturn") += 127;
mymap.at("Jupiter") = mymap.at("Saturn") + 9638;
	
for (auto& x: mymap) {
    std::cout << x.first << ": " << x.second << std::endl;
}

4.5 element search

(1)find

The prototype of the find function is as follows:

iterator find ( const key_type& k );
const_iterator find ( const key_type& k ) const;

The find function can be used to get the iterator of the element:

std::unordered_map<std::string,double> mymap1 = {
	    {"mom",5.4},
	    {"dad",6.1},
	    {"bro",5.9} };
	
string person = "dad";
unordered_map<std::string,double>::const_iterator got = mymap1.find(person);

if(got == mymap1.end()){
    cout << "not found" << endl;
}else{
    cout << got->first << " is " << got->second << endl; 
}

Notice how iterators are declared:

unordered_map<string,double>::const_iterator

(2)count

The member function count determines whether there is a key value k in the set. The prototype of the function is as follows:

size_type count ( const key_type& k ) const;

Where size_type is an integer variable. If there is key k in the unordered map, the return value is 1; otherwise, the return value is 0.

4.6 modification

(1) Element insertion

  • operator[]

    Using the operator map_name [key_name] = value, which overwrites the value value of the corresponding key. If the key value is a non-existent key, then the insertion of a new element is realized.

  • emplace()

    In unordered_ Insert a new element into the map (if its key is unique). This new element is constructed using args as an argument to the element constructor.

    Only if no element in the container has a key equivalent to the element to be placed (the key in the unordered_map is unique) Will be inserted.

    If inserted, this will actually increase the container size by one.

    There is a similar member function insert, which copies or moves existing objects into the container.

    // unordered_map::emplace
    #include <iostream>
    #include <string>
    #include <unordered_map>
    
    int main ()
    {
      std::unordered_map<std::string,std::string> mymap;
    
      mymap.emplace ("NCC-1701", "J.T. Kirk");
      mymap.emplace ("NCC-1701-D", "J.L. Picard");
      mymap.emplace ("NCC-74656", "K. Janeway");
    
      std::cout << "mymap contains:" << std::endl;
      for (auto& x: mymap)
        std::cout << x.first << ": " << x.second << std::endl;
    
      std::cout << std::endl;
      return 0;
    }
    
  • insert()

    The insertion of insert is similar to the insertion of replace. Only when the key is unique can it be inserted, and the size increases.

    The insertion form of insert is more flexible than that of empty:

    (1)	
    pair<iterator,bool> insert ( const value_type& val );
    (2)	
    template <class P>
        pair<iterator,bool> insert ( P&& val );
    (3)	
    iterator insert ( const_iterator hint, const value_type& val );
    (4)	
    template <class P>
        iterator insert ( const_iterator hint, P&& val );
    (5)	
    template <class InputIterator>
        void insert ( InputIterator first, InputIterator last );
    (6)	
    void insert ( initializer_list<value_type> il );
    
    /** Element insertion**/
    // insert
    unordered_map<string,double> myrecipe, mypantry = {{"milk",2.0},{"flour",1.5}};;					
    pair<string,double> myshopping ("baking powder",0.3);
    myrecipe.insert(myshopping);	// copy insertion
    myrecipe.insert(mypantry.begin(), mypantry.end());	// range inseration
    myrecipe.insert({{"sugar",0.8},{"salt",0.1},{"sugar",0.9}});		// initializer list inseration
    
    cout << "myrecipe contains: " << endl;
    for(auto& x:myrecipe){
        cout << x.first << ":" << x.second << " "; 
    }
    

(2) Element deletion

The erase() method is used to delete elements. There are many forms of deletion:

by position (1)iterator erase ( const_iterator position );
by key (2)size_type erase ( const key_type& k );
range (3)iterator erase ( const_iterator first, const_iterator last );
//erase
std::unordered_map<std::string,std::string> mymap3;

// populating container:
mymap3["U.S."] = "Washington";
mymap3["U.K."] = "London";
mymap3["France"] = "Paris";
mymap3["Russia"] = "Moscow";
mymap3["China"] = "Beijing";
mymap3["Germany"] = "Berlin";
mymap3["Japan"] = "Tokyo";

cout << endl;
cout << "------------------------------------------" << endl;
// Depending on the location, delete the first:
mymap3.erase(mymap3.begin());
// According to key
mymap3.erase("France");
// range
mymap3.erase(mymap3.find("Germany"), mymap3.end());

for (auto& x : mymap3) {
    cout << x.first << ": " << x.second << " ";
}

Topics: C++ Back-end