23

EDIT: Please note, I'm NOT asking why multimap can't contain duplicate keys.

What's the rationale behind multimap allowing duplicate key-value pairs? (not keys)

#include <map>
#include <string>
#include <iostream>

int
main(int argc, char** argv)
{
    std::multimap<std::string, std::string> m;
    m.insert(std::make_pair("A", "B"));
    m.insert(std::make_pair("A", "B"));
    m.insert(std::make_pair("A", "C"));
    std::cout << m.size() << std::endl;
    return 0;
}

This printed 3, which somewhat surprised me, I expected multimap to behave like a set of pairs, so I was expecting 2.

Intuitively, it's not consistent with C++ std::map behaviour, where insert does not always change the map (as opposed to operator[]).

Is there a rationale behind it, or it's just arbitrary?

Alex B
  • 82,554
  • 44
  • 203
  • 280
  • 3
    Maybe `std::set > >` is the container you are looking for? It would keep two entries. – Sjoerd Apr 12 '11 at 08:24
  • 1
    @Sjoerd Yes, but that's not the question. The question is why it behaves the way it does. I'm not looking for a solution to a particular problem. – Alex B Apr 12 '11 at 08:28
  • 2
    That's why I made it a comment, not an answer. Also for future viewers who are looking for a solution. – Sjoerd Apr 12 '11 at 08:40
  • 5
    `std::map >` is even better than `std::set >`. Too bad I can't edit my first comment anymore... – Sjoerd Apr 12 '11 at 08:49

7 Answers7

21

Multimap only has a predicate ordering the keys. It has no method to determine whether the values are equal. Is value "A" a duplicate of value "a"? Without a second predicate for the values, there's no telling. Therefore, it doesn't even make sense to talk about duplicate values in a multimap.

If you would like a container that stores pairs, and enforces the unique-ness of both parts of the pair, look at boost::multi_index_container. It's very flexible, but takes a load of arguments as a result.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 4
    While your answer is reasonable, a minor nitpick: I think the first paragraph reverses cause and effect. Multimap does not enforce uniqueness of values per key *because* it has only predicate for keys, but rather it only has predicate for keys *because* it doesn't enforce the uniqueness of values per key. – Alex B Apr 13 '11 at 23:39
  • 2
    In a sense the question has the same reversal of logic. You could have a container that does not allow duplicate key-value pairs, but that wouldn't be `std::multimap` anymore. – MSalters Apr 14 '11 at 07:41
  • 1
    *"a container that stores pairs, and enforces the unique-ness of both parts..."* - or simply `std::set< std::pair >` – bloody Apr 28 '22 at 20:37
12

EDIT: This answer does not answer the current question anymore. I'll keep it as it is because it got upvoted a lot so it must be useful for some.

The multi in multimap stands for the fact that the same key can occur multiple times.

The standard puts no limit on the type used as value, so one cannot assume that operator==() is defined. Because we don't want the result of your code depend on whether the operator==() is defined or not, it is never used.

std::multimap is not a replacement for std::map. As you noticed, it behaves differently when the same key is inserted multiple times. If you want std::map's behaviour, use std::map.

There is also a std::multiset.

The rational: sometimes one would like to keep all old entries for the same key around as well. [TBD: Insert some example here]

Personally, I barely ever use std::multimap. If I want multiple entries for the same key, I usually rely on std::map<std::vector<T> >.

Sjoerd
  • 6,837
  • 31
  • 44
  • 1
    Does anyone know a good use case for std::multimap? It would improve my answer. – Sjoerd Apr 12 '11 at 08:21
  • I'd put an emphasis on `key` in the first sentence, as the OP seems to believe the value matters too. – Xeo Apr 12 '11 at 08:23
  • I *know* that key can't be repeated and stated it in the very first sentence of the question. But it repeats key-value pairs, which seem unnecessary. I can't see a use case for it. – Alex B Apr 12 '11 at 08:27
  • I find `std::multimap` easier to manage than `map>`. It might be more efficient with frequent additions/deletions. Any 1:N mapping would be suitable for multimap. – edA-qa mort-ora-y Apr 12 '11 at 08:28
  • Any container that might contain duplicates would be suitable for a `multimap` if key lookup is required. I'm sure anybody can think of any number of reasons why you might want duplicates in a collection?! – edA-qa mort-ora-y Apr 12 '11 at 08:30
  • @edA-qa `map>` remembers the order of insertions. `map>` removes duplicates (as the OP expected). Each can be a reason not to use `std::multimap`. But you are right that std::multimap could be more efficient when faced with frequent deletions - although by the time that would be noticable, you might be better off using a real database. – Sjoerd Apr 12 '11 at 08:39
  • @Sjoerd good use case for std::multimap - dictionary when key is word and value a collection of multiple meanings – dubnde Apr 12 '11 at 10:03
  • @Sjoerd : here's a good use of multimap to print all zero-sum subarrays in O(n) time complexity - https://www.techiedelight.com/find-sub-array-with-0-sum/ – totjammykd Sep 25 '19 at 23:10
  • map> implies that you care about the order of the T for each K. If you don't care then a map> makes more sense. And now you're storing a map plus a multiset for each element in the map. Maybe there's more overhead in that they just having a single multimap? – Eyal Jun 07 '20 at 14:24
2

The values are allowed to be duplicates because they are not required to be comparable to each other. The container cannot do anything with the values besides copy them in. This enables types like multimap< int, my_class >.

If duplicate key-value pairs are undesirable, then use set< pair< T, U > > and use lower_bound to find the first match to a given key.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
1

As you know, multimap allows to have multiple keys. Since it does not place any constraints on values comparability, it is unable to check, if values haven't been doubled.

If you want to have some dictionary data structure which allows for duplicate keys, but not key-value pairs, you would have to ensure that values are comparable.

Let's say we have a game of some sort, where there is 2D world of sqaure fields, and you can put items on fields. You can have multimap<Field, Item>, which will allow you to keep two identical items on the field. Items don't have to be comparable here.

x13n
  • 4,103
  • 2
  • 21
  • 28
1

My reasoning is multimap is based on the Key lookup/insertion and not on the value. So whether the value on duplicate keys is the same or not does not play a part when elements are being inserted.

23.3.2 Class template multimap

1 A multimap is a kind of associative container that supports equivalent keys (possibly containing multiple copies of the same key value) and provides for fast retrieval of values of another type T based on the keys.

dubnde
  • 4,359
  • 9
  • 43
  • 63
0

"multimap" is meant to support 'multiple' keys unlike simple "map". Since it allows multiple keys, it won't bother for their values, so it shows 3 elements in your example. The other difference is, one can not have operator [] for multimap.

iammilind
  • 68,093
  • 33
  • 169
  • 336
0

A use of duplicate [map,value] pairs is to count the number of occurrences of say a word on a page of a book, be it no times, thus no entry in the multimap for that word, be it once with one entry, or more than once with the number of occurrences in multimap for make_pair(word, page_number). It was more by accident that design that I found this usage.