Map это Iterable состоящее из пар ключ значение (также называемых связкой или ассоциативным массивом).
Scala Объект Predef предоставляет неявное преобразование, позволяющее записать пару (ключ, значение) используя альтернативный синтаксис вида ключ -> значение . Например, Map("x" -> 24, "y" -> 25, "z" -> 26) означает тоже самое что и Map(("x", 24), ("y", 25), ("z", 26)), но читается лучше.
Основные операции на мапах аналогичны темже операциям на множества. Рассмотрим в следующей таблице обобщеный и сгруппированный по категориям список методов на мапах:
- Запросы операции
apply,get,getOrElse,contains, иisDefinedAt. Они превращают мапы в частично определенные функции от ключей к значениям. Основной “запросный метод” на мапах это :def get(key): Option[Value]. Операция “m get key” проверяет содержит ли мапа связанное значение для ключаkey. Если да, то возвращает это связанное значение обернутое вSome. Если же нет, тоgetвозвращаетNone. На мапах еще определен методapply, которое напрямую возвращает связанное с заданным ключем значение, без оборачивания его вOption. В этом случае, когда ключ не определен, будет брошено исключение. - Добавление и обновления
+,++,updated, которые позволяют добавлять новые пары к мапам или изменять существующие. - Удаления
-,--, которые позволяют удалять пары из мап. - Создание подколлеций
keys,keySet,keysIterator,values,valuesIterator, которые возвращают ключи и значения мап отдельно в различных формах. - Трансформации
filterKeysиmapValues, которые создают новую мапу через фильтрацию и преобразования элементов существующей мапы.
Операции на Классе Map
| ПРИМЕР | ЧТО ДЕЛАЕТ |
|---|---|
| Запросы: | |
ms get k |
Возвращает значение связанное с ключом k в мапе ms обернутое в опшен, None если значение не найдено. |
ms(k) |
(либо эквивалент ms apply k) Возвращает напрямую значение, связанное с ключом k на мапе ms, или исключение, если оно не найдено. |
ms getOrElse (k, d) |
Значение, связанное с ключом k на мапе ms, или значением по умолчанию d, если не найдено. |
ms contains k |
Проверяет, содержит ли ms значение для ключа k. |
ms isDefinedAt k |
Тоже самое что и contains. |
| Подколлекции: | |
ms.keys |
Итерируемая коллекция, содержащая каждый ключ из мапы ms. |
ms.keySet |
Множество, содержащее каждый ключ из ms. |
ms.keysIterator |
Итератор, выдающий каждый ключ из ms. |
ms.values |
Итерируемая коллекция, содержащая каждое значение, связанное с ключом из ms. |
ms.valuesIterator |
Итератор, выдающий каждое значение, связанное с ключом из ms. |
| Преобразования: | |
ms.view filterKeys p |
Отображение мапы, содержащее только те пары из ms, в которых ключ удовлетворяет предикату p. |
ms.view mapValues f |
Представление мапы ms к значениям которой применена функция f. |
Неизменяемые мапы поддерживают операции добавления и удаления элементов через возврат новых Мапов, как описано в следующей таблице.
Операции на Классе immutable.Map
| ПРИМЕР | ЧТО ДЕЛАЕТ |
|---|---|
| Добавления и обновления: | |
ms.updated(k, v)или ms + (k -> v) |
Мапа, содержащая все пары из ms, а также ассоциативную связь k -> v от ключа k к значению v. |
| Удаления: | |
ms remove kили ms - k |
Мапа, содержащая все пары ms за исключением пары с ключом k. |
ms removeAll ksили ms -- ks |
Мапа, содержащая все пары из ms за исключением пары с ключом из ks. |
Изменяемые мапы поддерживают дополнительные операции, которые представленным в таблице ниже.
Операции на Классе mutable.Map
| ПРИМЕР | ЧТО ДЕЛАЕТ |
|---|---|
| Добавления и обновления: | |
ms(k) = v |
(либо эквивалент ms.update(x, v)). Добавляет связь от ключа k к значению v в мапе ms через побочный эффект, перезаписывая любую предыдущую связь с k. |
ms.addOne(k -> v)либо ms += (k -> v) |
Добавляет связь от ключа k к значению v в мапе ms через побочный эффект и возвращает сам ms. |
ms addAll xvsлибо ms ++= kvs |
Добавляет все пары из kvs к ms через побочный эффект и возвращает сам ms. |
ms.put(k, v) |
Добавляет связь от ключа k к значению v в мапе ms и возвращает любое значение, которое было ранее связанно с k (опционально). |
ms getOrElseUpdate (k, d) |
Если ключ k определен на мапе ms, возвращает связанное с ним значение. В противном случае добавляет к ms связь вида k -> d и возвращает d. |
| Удаления: | |
ms subtractOne kлибо ms -= k |
Удаляет ассоциированную связь с ключом k из мапы ms побочным эффектом и возвращает сам ms. |
ms subtractAll ksлибо ms --= ks |
Удаляет все пары связанные с ключами ks из мапы ms побочным эффектом и возвращает сам ms. |
ms remove k |
Удаляет любую пару связанную с ключом k из ms и возвращает значение, которое ранее было связанное с k (опционально). |
ms filterInPlace p |
Оставляет только те пары в мапе ms, у которых ключ, удовлетворяет предикату p. |
ms.clear() |
Удаляет все пары из мапы ms |
| Преобразования: | |
ms mapValuesInPlace f |
Преобразует все значения в мапе ms используя функцию f. |
| Клонирования: | |
ms.clone |
Возвращает новую изменяемую мапу с теми же парами, что и у ms. |
Операции добавления и удаления в мапах совпадают с операциями добавления и удаления у множеств. Изменяемая мапа m обычно обновляется через замену значений в самой себе, используя два варианта синтаксиса m(key) = value или m += (key -> value). Существует также вариант m.put(key, value), который возвращает Option, содержащее значение, ранее связанного с key, или None, если key не было в мапе.
Функция getOrElseUpdate полезна для доступа к мапам, работающим в качестве кэша. Допустим, у вас есть дорогая для вычисления операция, вызываемая функцией f:
scala> def f(x: String) = {
println("taking my time."); sleep(100)
x.reverse }
f: (x: String)String
Допустим, что f без побочных эффектов, поэтому повторное обращение к функции с тем же аргументом всегда будет давать один и тот же результат. В этом случае можно сэкономить время, сохранив ранее вычисленное выражение связав аргумент с результатом f на мапе и вычислять f только в том случае, если результат для аргумента не находится в мапе. Можно сказать, что мапа представляет собой кэш для вычислений функции f.
scala> val cache = collection.mutable.Map[String, String]()
cache: scala.collection.mutable.Map[String,String] = Map()
Теперь вы можете создать более эффективную кэшированную версию функции f:
scala> def cachedF(s: String) = cache.getOrElseUpdate(s, f(s))
cachedF: (s: String)String
scala> cachedF("abc")
taking my time.
res3: String = cba
scala> cachedF("abc")
res4: String = cba
Обратите внимание, что второй аргумент для getOrElseUpdate вызывается “по имени”, поэтому вычисление f("abc") производится только если getOrElseUpdate запросит значения второго аргумента, точнее если его первый аргумент не найден в мапе cache. Вы могли бы реализовать cachedF самостоятельно, используя только базовые операции с мапами, но для этого понадобилось бы больше кода:
def cachedF(arg: String) = cache get arg match {
case Some(result) => result
case None =>
val result = f(x)
cache(arg) = result
result
}
Contributors to this page:
Contents
- Введение
- Изменяемые и Неизменяемые Коллекции
- Трейт Iterable
- Последовательности. Трейт Seq, IndexedSeq и LinearSeq
- Множества
- Мапы
- Реализации Неизменяемых Коллекций
- Реализации Изменяемых Коллекций
- Массивы
- Строки
- Показатели производительности
- Равенство
- Отображения
- Итераторы
- Создание коллекций с нуля
- Преобразования между Java и Scala коллекциями