Общие принципы
Поиск по ключу во всех трёх ассоциативных контейнерах Qt выполняется методом find(), который возвращает итератор, указывающий на найденный элемент.
Поведение метода единообразно для QMap, QHash и QMultiMap:
- Если элемент найден — возвращается итератор на него.
- Если элемент не найден — возвращается
end(). - Если с данным ключом найдено несколько значений — возвращается итератор на последнее добавленное значение.
Именно поэтому после вызова find() обязательно проверять результат на равенство end() — иначе обращение к несуществующему элементу приведёт к неопределённому поведению.
Фрагменты кода
QMap
QMap<int, QString> map;
QMap<int, QString>::Iterator it = map.find(123);
if (it != map.end()) {
QString myValue = it.value(); // ключ найден
}
QHash
QHash<int, QString> h;
QHash<int, QString>::Iterator it = h.find(123);
if (it != h.end()) {
QString myValue = it.value(); // ключ найден
}
QMultiMap
QMultiMap<int, QString> m;
QMultiMap<int, QString>::Iterator it = m.find(123);
if (it != m.end()) {
QString myValue = it.value(); // ключ найден
}
Особенности каждого контейнера
| Контейнер | Особенности поиска |
|---|---|
QMap | Упорядочен по ключу (красно-чёрное дерево). Поиск — O(log n). Ключи уникальны. |
QHash | Неупорядочен (хеш-таблица). Поиск в среднем — O(1), в худшем — O(n). Ключи уникальны. |
QMultiMap | Упорядочен, допускает несколько значений с одним ключом. Поиск — O(log n). find() вернёт итератор на одно из значений (обычно последнее добавленное). |
Важные замечания
- Всегда проверяйте
it != container.end(). Обращение кit.value()приit == end()— неопределённое поведение. find()вQMultiMapвозвращает лишь одно значение. Чтобы получить все значения по ключу, используйтеequal_range():cppauto range = m.equal_range(123); for (auto it = range.first; it != range.second; ++it) { qDebug() << it.value(); }Или методvalues(key), возвращающийQListвсех значений.constFind()для константных контейнеров. Если контейнер не должен изменяться, используйтеconstFind()иconst_iterator— это безопаснее и яснее по смыслу:cppQMap<int, QString>::const_iterator it = map.constFind(123);- Альтернатива —
contains()+value(). Для простого извлечения значения без итерации удобнее:cppif (map.contains(123)) { QString v = map.value(123); }Но такой подход выполняет два поиска вместо одного, что менее эффективно, чемfind(). - Оператор
[]создаёт элемент. В отличие отfind(), обращениеmap[123]добавит запись с ключом123и значением по умолчанию, если её не было. Для чтения без модификации это опасно. - Итераторы инвалидируются при изменении контейнера. После вставки или удаления элементов ранее полученные итераторы могут стать недействительными.
QMultiHash— аналогQMultiMapдля хеш-таблиц, с теми же принципами поиска и работы с дублирующимися ключами.
Итог
Поиск по ключу в QMap, QHash и QMultiMap выполняется единообразно через метод find(), возвращающий итератор или end(). Главное правило — всегда проверять результат на end() перед разыменованием. Для контейнеров с дублирующимися ключами (QMultiMap, QMultiHash) используйте equal_range() или values(), чтобы получить все значения по ключу, а не только одно.