Готовые методы реализаций

Поиск с помощью итераторов в QMap, QHash и QMultiMap

обновлено 1 618 просмотров

Общие принципы

Поиск по ключу во всех трёх ассоциативных контейнерах Qt выполняется методом find(), который возвращает итератор, указывающий на найденный элемент.

Поведение метода единообразно для QMapQHash и 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() вернёт итератор на одно из значений (обычно последнее добавленное).

Важные замечания

  1. Всегда проверяйте it != container.end(). Обращение к it.value() при it == end() — неопределённое поведение.
  2. 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 всех значений.
  3. constFind() для константных контейнеров. Если контейнер не должен изменяться, используйте constFind() и const_iterator — это безопаснее и яснее по смыслу:cppQMap<int, QString>::const_iterator it = map.constFind(123);
  4. Альтернатива — contains() + value(). Для простого извлечения значения без итерации удобнее:cppif (map.contains(123)) { QString v = map.value(123); }Но такой подход выполняет два поиска вместо одного, что менее эффективно, чем find().
  5. Оператор [] создаёт элемент. В отличие от find(), обращение map[123] добавит запись с ключом 123 и значением по умолчанию, если её не было. Для чтения без модификации это опасно.
  6. Итераторы инвалидируются при изменении контейнера. После вставки или удаления элементов ранее полученные итераторы могут стать недействительными.
  7. QMultiHash — аналог QMultiMap для хеш-таблиц, с теми же принципами поиска и работы с дублирующимися ключами.

Итог

Поиск по ключу в QMapQHash и QMultiMap выполняется единообразно через метод find(), возвращающий итератор или end(). Главное правило — всегда проверять результат на end() перед разыменованием. Для контейнеров с дублирующимися ключами (QMultiMapQMultiHash) используйте equal_range() или values(), чтобы получить все значения по ключу, а не только одно.