/* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2009, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ // $Id: MutableMapTemplate.scala 18545 2009-08-22 14:10:22Z extempore $ package scala.collection.generic import scala.collection._ /** <p> * A generic template for mutable maps from keys of type <code>A</code> to * values of type <code>B</code>. * </p> * <p> * To implement a concrete mutable map, you need to provide implementations * of the following methods: * </p><pre> * <b>def</b> get(key: A): Option[B] * <b>def</b> iterator: Iterator[(A, B)] * <b>def</b> += (kv: (A, B)): <b>this.type</b> * <b>def</b> -= (key: A): <b>this.type</b></pre> * <p> * If you wish that methods <code>like</code>, <code>take</code>, * <code>drop</code>, <code>filter</code> return the same kind of map, you * should also override: * </p><pre> * <b>def</b> empty: This</pre> * <p> * If you to avoid the unncessary construction of an <code>Option</code> * object, you could also override <code>apply</code>, <code>update</code>, * and <code>delete</code>. * </p> * <p> * It is also good idea to override methods <code>foreach</code> and * <code>size</code> for efficiency. * </p> */ trait MutableMapTemplate[A, B, +This <: MutableMapTemplate[A, B, This] with mutable.Map[A, B]] extends MutableMapTemplateBase[A, B, This] with Builder[(A, B), This] with Growable[(A, B)] with Shrinkable[A] with Cloneable[This] { self => /** <p> * A common implementation of <code>newBuilder</code> for all mutable maps * in terms of <code>empty</code>. * </p> * <p> * Overrides <code>MapTemplate</code> implementation for better efficiency. * </p> */ override protected[this] def newBuilder: Builder[(A, B), This] = empty /** Adds a new mapping from <code>key</code> * to <code>value</code> to the map. If the map already contains a * mapping for <code>key</code>, it will be overridden. * * @param key The key to update * @param value The new value */ def put(key: A, value: B): Option[B] = { val r = get(key) update(key, value) r } /** Adds a new mapping from <code>key</code> * to <code>value</code> to the map. If the map already contains a * mapping for <code>key</code>, it will be overridden. * * @param key The key to update * @param value The new value * @return An option consisting of value associated previously associated with `key` in the map, * or None if `key` was not yet defined in the map. */ def update(key: A, value: B) { this += ((key, value)) } /** Add a new key/value mapping this map. * @param kv the key/value pair. * @return the map itself */ def += (kv: (A, B)): this.type /** Create a new map consisting of all elements of the current map * plus the given mapping from <code>key</code> to <code>value</code>. * * @param key The key to ad * @param value The new value * @return A fresh immutable map */ override def updated[B1 >: B](key: A, value: B1): mutable.Map[A, B1] = this + ((key, value)) /** If given key is already in this map, returns associated value * Otherwise, computes value from given expression `op`, stores with key * in map and returns that value. */ def cached(key: A, op: => B) = get(key) match { case Some(v) => v case None => val v = op; update(key, v); v } /** Add a new key/value mapping and return the map itself. * * @param kv the key/value mapping to be added */ @deprecated("This operation will create a new map in the future. To add an element as a side\n"+ "effect to an existing map and return that map itself, use +=. If you do want\n"+ "to create a fresh map, you can use `clone() +=' to avoid a @deprecated warning.") def + (kv: (A, B)): this.type = { update(kv._1, kv._2); this } /** Adds two or more key/value mappings and return the map itself. * with the added elements. * * @param elem1 the first element to add. * @param elem2 the second element to add. * @param elems the remaining elements to add. */ @deprecated("This operation will create a new map in the future. To add an element as a side\n"+ "effect to an existing map and return that map itself, use +=. If you do want to\n"+ "create a fresh map, you can use `clone() +=` to avoid a @deprecated warning.") def +(elem1: (A, B), elem2: (A, B), elems: (A, B)*): this.type = this += elem1 += elem2 ++= elems /** Adds a number of elements provided by a traversable object * via its <code>iterator</code> method and returns * either the collection itself (if it is mutable), or a new collection * with the added elements. * * @param iter the traversable object. */ @deprecated("This operation will create a new map in the future. To add elements as a side\n"+ "effect to an existing map and return that map itself, use ++=. If you do want\n"+ "to create a fresh map, you can use `clone() ++=` to avoid a @deprecated warning.") def ++(iter: Traversable[(A, B)]): this.type = { for (elem <- iter) +=(elem); this } /** Adds a number of elements provided by an iterator * via its <code>iterator</code> method and returns * the collection itself. * * @param iter the iterator */ @deprecated("This operation will create a new map in the future. To add elements as a side\n"+ "effect to an existing map and return that map itself, use ++=. If you do want\n"+ "to create a fresh map, you can use `clone() +=` to avoid a @deprecated warning.") def ++(iter: Iterator[(A, B)]): this.type = { for (elem <- iter) +=(elem); this } /** If given key is defined in this map, remove it and return associated value as an Option. * If key is not present return None. * @param key the key to be removed */ def remove(key: A): Option[B] = { val r = get(key) this -= key r } /** Delete a key from this map if it is present. * @param key the key to be removed * @note same as `delete`. */ def -= (key: A): this.type /** Delete a key from this map if it is present and return the map itself. * @param key the key to be removed */ @deprecated("This operation will create a new map in the future. To add elements as a side\n"+ "effect to an existing map and return that map itself, use -=. If you do want\n"+ "to create a fresh map, you can use `clone() -=` to avoid a @deprecated warning.") override def -(key: A): This = { -=(key); thisCollection } /** If given key is defined in this map, remove it and return associated value as an Option. * If key is not present return None. * @param key the key to be removed */ @deprecated("Use `remove' instead") def removeKey(key: A): Option[B] = remove(key) /** Removes all elements from the set. After this operation is completed, * the set will be empty. */ def clear() { for ((k, v) <- this.iterator) -=(k) } /** Check if this map maps <code>key</code> to a value. * Return that value if it exists, otherwise put <code>default</code> * as that key's value and return it. */ def getOrElseUpdate(key: A, default: => B): B = get(key) match { case Some(v) => v case None => val d = default; this(key) = d; d } /** This function transforms all the values of mappings contained * in this map with function <code>f</code>. * * @param f The transformation to apply */ def transform(f: (A, B) => B): this.type = { this.iterator foreach { case (key, value) => update(key, f(key, value)) } this } /** Retain only those mappings for which the predicate * <code>p</code> returns <code>true</code>. * * @param p The test predicate */ @deprecated("cannot be type inferred because of retain in Iterable.") def retain(p: (A, B) => Boolean): this.type = { for ((k, v) <- this) if (!p(k, v)) -=(k) this } override def clone(): This = empty ++= thisCollection /** The result when this map is used as a builder */ def result: This = thisCollection /** Removes two or more elements from this collection and returns * the collection itself. * * @param elem1 the first element to remove. * @param elem2 the second element to remove. * @param elems the remaining elements to remove. */ @deprecated("Use -= instead if you intend to remove by side effect from an existing collection.\n"+ "Use `clone() -=' if you intend to create a new collection.") override def -(elem1: A, elem2: A, elems: A*): This = { this -= elem1 -= elem2 --= elems thisCollection } /** Removes a number of elements provided by a Traversable object and returns * the collection itself. * * @param iter the Traversable object. */ @deprecated("Use --= instead if you intend to remove by side effect from an existing collection.\n"+ "Use `clone() --=' if you intend to create a new collection.") override def --(iter: Traversable[A]): This = { for (elem <- iter) -=(elem) thisCollection } /** Removes a number of elements provided by an iterator and returns * the collection itself. * * @param iter the iterator */ @deprecated("Use --= instead if you intend to remove by side effect from an existing collection.\n"+ "Use `clone() --=' if you intend to create a new collection.") override def --(iter: Iterator[A]): This = { for (elem <- iter) -=(elem) thisCollection } }