Add QMap::insert(const QMap &map)

As opposed to unite(), this inserts one map into the other
without duplicating elements.

Task-number: QTBUG-35544
Change-Id: Ie8ab350b29148851a3176cef1007e8a4ca82c273
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Mårten Nordheim 2019-11-06 18:04:45 +01:00
parent 9c124b1b0a
commit d98a1ef902
4 changed files with 169 additions and 0 deletions

View File

@ -1150,6 +1150,20 @@ void QMapDataBase::freeData(QMapDataBase *d)
\sa insertMulti()
*/
/*! \fn template <class Key, class T> void QMap<Key, T>::insert(const QMap<Key, T> &map)
\since 5.15
Inserts all the items in \a map into this map.
If a key is common to both maps, its value will be replaced with
the value stored in \a map.
\note If \a map contains multiple entries with the same key then the
final value of the key is undefined.
\sa insertMulti()
*/
/*! \fn template <class Key, class T> QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &key, const T &value)
Inserts a new item with the key \a key and a value of \a value.

View File

@ -578,6 +578,7 @@ public:
const_iterator upperBound(const Key &key) const;
iterator insert(const Key &key, const T &value);
iterator insert(const_iterator pos, const Key &key, const T &value);
void insert(const QMap<Key, T> &map);
iterator insertMulti(const Key &key, const T &value);
iterator insertMulti(const_iterator pos, const Key &akey, const T &avalue);
QMap<Key, T> &unite(const QMap<Key, T> &other);
@ -788,6 +789,49 @@ typename QMap<Key, T>::iterator QMap<Key, T>::insert(const_iterator pos, const K
}
}
template <class Key, class T>
Q_INLINE_TEMPLATE void QMap<Key, T>::insert(const QMap<Key, T> &map)
{
if (d == map.d)
return;
detach();
Node *n = d->root();
auto it = map.cbegin();
const auto e = map.cend();
while (it != e) {
// Insertion here is based on insert(Key, T)
auto parent = d->end();
bool left = true;
Node *lastNode = nullptr;
while (n) {
parent = n;
if (!qMapLessThanKey(n->key, it.key())) {
lastNode = n;
n = n->leftNode();
left = true;
} else {
n = n->rightNode();
left = false;
}
}
if (lastNode && !qMapLessThanKey(it.key(), lastNode->key)) {
lastNode->value = it.value();
n = lastNode;
} else {
n = d->createNode(it.key(), it.value(), parent, left);
}
++it;
if (it != e) {
// Move back up the tree until we find the next branch or node which is
// relevant for the next key.
while (n != d->root() && qMapLessThanKey(n->key, it.key()))
n = static_cast<Node *>(n->parent());
}
}
}
template <class Key, class T>
Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &akey,
const T &avalue)

View File

@ -71,6 +71,7 @@ private slots:
void setSharable();
void insert();
void insertMap();
void checkMostLeftNode();
void initializerList();
void testInsertWithHint();
@ -1265,6 +1266,101 @@ void tst_QMap::insert()
}
}
void tst_QMap::insertMap()
{
{
QMap<int, int> map;
map.insert(1, 1);
map.insert(2, 2);
map.insert(0, -1);
QMap<int, int> map2;
map2.insert(0, 0);
map2.insert(3, 3);
map2.insert(4, 4);
map.insert(map2);
QCOMPARE(map.count(), 5);
for (int i = 0; i < 5; ++i)
QCOMPARE(map[i], i);
}
{
QMap<int, int> map;
for (int i = 0; i < 10; ++i)
map.insert(i * 3, i);
QMap<int, int> map2;
for (int i = 0; i < 10; ++i)
map2.insert(i * 4, i);
map.insert(map2);
QCOMPARE(map.count(), 17);
for (int i = 0; i < 10; ++i) {
// i * 3 == i except for i = 4, 8
QCOMPARE(map[i * 3], (i && i % 4 == 0) ? i - (i / 4) : i);
QCOMPARE(map[i * 4], i);
}
auto it = map.cbegin();
int prev = it.key();
++it;
for (auto end = map.cend(); it != end; ++it) {
QVERIFY(prev < it.key());
prev = it.key();
}
}
{
QMap<int, int> map;
map.insert(1, 1);
QMap<int, int> map2;
map.insert(map2);
QCOMPARE(map.count(), 1);
QCOMPARE(map[1], 1);
}
{
QMap<int, int> map;
QMap<int, int> map2;
map2.insert(1, 1);
map.insert(map2);
QCOMPARE(map.count(), 1);
QCOMPARE(map[1], 1);
}
{
QMap<int, int> map;
map.insert(0, 0);
map.insert(1, 1);
map.insert(2, 2);
// Test inserting into self, nothing should happen
map.insert(map);
QCOMPARE(map.count(), 3);
for (int i = 0; i < 3; ++i)
QCOMPARE(map[i], i);
}
{
// Here we use a QMultiMap and insert that into QMap,
// since it has multiple values with the same key the
// ordering is undefined so we won't test that, but
// make sure this isn't adding multiple entries with the
// same key to the QMap.
QMap<int, int> map;
QMultiMap<int, int> map2;
map2.insert(0, 0);
map2.insert(0, 1);
map2.insert(0, 2);
map.insert(map2);
QCOMPARE(map.count(), 1);
}
}
void tst_QMap::checkMostLeftNode()
{
QMap<int, int> map;

View File

@ -59,6 +59,8 @@ private slots:
void insertion_string_int2();
void insertion_string_int2_hint();
void insertMap();
};
@ -269,6 +271,19 @@ void tst_QMap::insertion_string_int2_hint()
}
}
void tst_QMap::insertMap()
{
QMap<int, int> map;
for (int i = 0; i < 100000; ++i)
map.insert(i * 4, 0);
QMap<int, int> map2;
for (int i = 0; i < 50000; ++i)
map2.insert(i * 7, 0);
QBENCHMARK_ONCE {
map.insert(map2);
}
}
QTEST_MAIN(tst_QMap)
#include "main.moc"