In the article "Using <map> Library to create an associative container," We discussed the Map Association container in the standard library. But that's just part of the map container. The standard library also defines a Multimap container, which is similar to a map, but it allows duplicate keys. This attribute makes Multimap more useful than expected: for example, the same person in the phone book can have more than two phone numbers, the file system can map multiple symbolic links to the same physical file, or the DNS server can map several URLs to the same IP address. On these occasions, you can look like this:
Note: Pseudo code
Multimap <string, string> phonebook;
Phonebook.insert ("Harry", "8225687"); Home phone
Phonebook.insert ("Harry", "555123123"); Unit Telephone
Phonebook.insert ("Harry", "2532532532"); Mobile phone
The ability to store duplicate keys in Multimap greatly affects its interface and use. So how do you create an associative container for a non unique key? The answer is to use the Multimap container defined in the <map> library.
Ask a question
Unlike map, Multimap can contain duplicate keys. This poses a problem: how overloaded subscript operators return multiple association values of the same key. Take the following pseudo code as an example:
String phone=phonebook["Harry];
The solution to the problem of the designer of the standard library is to drop the label operator from the Multimap. Therefore, there are different ways to insert and get elements, and to do error handling.
Insert
Suppose you need to develop a DNS daemon (that is, a service program in a Windows system) that maps IP addresses to matching URL strings. You know that in some cases the same IP address is to be associated with multiple URLs. These URLs all point to the same site. In this case, you should use Multimap instead of map. For example:
#include <map>
#include <string>
Multimap <string, string> Dns_daemon;
Inserts an element with the insert () member function instead of the subscript operator. Insert () has a parameter of type pair. In the use <map> Library to create an association container we demonstrated how to use the Make_pair () helper function to accomplish this task. You can also use it as follows:
Dns_daemon.insert (Make_pair ("213.108.96.7", "cppzone.com"));
In the Insert () call above, the string "213.108.96.7" is the key, and "cppzone.com" is the value associated with it. The same keys are inserted at a later time, with different associated values:
Dns_daemon.insert (Make_pair ("213.108.96.7", "cppluspluszone.com"));
Therefore, Dns_daemon contains two elements with the same key value. Note that the values returned by Multimap::insert () and Map::insert () are different.
typedef pair <CONST Key, t> value_type;
Iterator
Insert (const value_type&); #1 Multimap
Pair <iterator, bool>
Insert (const value_type&); #2 Map
The Multimap::insert () member function returns the iteration pointer to the newly inserted element, that is, iterator (Multimap::insert () always succeeds). But Map::insert () returns Pair<iterator, Bool>, where the bool value indicates whether the insert operation was successful.
Find a single value
Like the map, Multimap has two overloaded find () member functions:
Iterator Find (const key_type& k);
Const_iterator Find (const key_type& k) const;
Find (k) returns an iterative pointer to the first pair that matches the key K, which means that the function is most useful when you want to check if there is at least one value associated with the key, or if you need only the first match. For example:
typedef multimap <string, string> Mmss;
void func (const MMSS & DNS)
{
Mmss::const_iterator cit=dns.find ("213.108.96.7");
if (CIT!= dns.end ())
cout << "213.108.96.7 found" <<endl;
Else
cout << "not Found" <<endl;
}
Handling Multiple Association values
The Count (k) member function returns the number that is associated with a given key. The following example reports how many values are associated with the key "213.108.96.7":
Cout<<dns.count ("213.108.96.7")//output:2
<< "elements associated" <<endl;
To access multiple values in the Multimap, use the Equal_range (), Lower_bound (), and Upper_bound () member functions:
Equal_range (k): This function finds all the values associated with K. Returns the pair of the iteration pointer, which marks the start and end ranges. The following example shows all the values associated with the key "213.108.96.7":
typedef multimap <string, String>::const_iterator CIT;
typedef pair<cit, cit> Range;
Range Range=dns.equal_range ("213.108.96.7");
for (CIT I=range.first; i!=range.second; ++i)
cout << i->second << Endl; Output:cpluspluszone.com
Cppzone.com
Lower_bound () and Upper_bound (): Lower_bound (k) finds the first value associated with the key K, and Upper_bound (k) is the element that finds the first key value larger than K. The following example demonstrates using Upper_bound () to locate the first element whose key value is greater than "213.108.96.7". Typically, when a key is a string, there is a lexicography comparison:
Dns.insert (Make_pair ("219.108.96.70", "pythonzone.com"));
CIT cit=dns.upper_bound ("213.108.96.7");
if (Cit!=dns.end ())//found anything?
cout<<cit->second<<endl; Display:pythonzone.com
If you want to display all of the values that follow, you can use a loop like this:
Inserting multiple values with the same key
Dns.insert (Make_pair ("219.108.96.70", "pythonzone.com"));
Dns.insert (Make_pair ("219.108.96.70", "python-zone.com"));
Gets the iteration pointer for the first value
CIT cit=dns.upper_bound ("213.108.96.7");
Output: pythonzone.com,python-zone.com
while (Cit!=dns.end ())
{
cout<<cit->second<<endl;
++cit;
}
Conclusions
Although map and Multimap have the same interface, the important difference is that duplicate keys, design and use are treated differently. Also note the nuances of the insert () member function in each container.