summaryrefslogblamecommitdiff
path: root/src/library/scala/collection/mutable/MapLike.scala
blob: 92f1b5bba61617111d1012685117d371dcf64094 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                                                          
                                                                          




                                                                          
       

 



                        
 


























                                                                              

              
   

                                                                
                               




                          

                                     




                                                                               
                                                                            
          

                                                                        
 
                                              
                                                                     
                                                          



                                    




                                          
 


                                                                     
    



                                                                                                     
     
                                                         
 


                                           
     
                                
 
                                                                    

                                                                         
                                 

                                         
     
                                                                                              
 








                                                                           
                                                            
    
                                                    
     



                                                                                                  
 
                                                                    





                                                 



                                                                                                  
                                    
 
                                                                
                                                      

                                                                          
    
                                             
     



                                                                                                 

                                                       
                                                      
                            


                                



                                                                                                
 

                                                                                              

                                         




                                   
 



                                                  
                            


                                                                            
     


                                                                                                
                                                  



                                                                                              
     
                                                                                     
 



                                                                           
                                                     
















                                                                        
                           




                                                     
                                                        


                                               
     
                                                                       





                                                 
                  

                                                      
                         






                                                                   
     


                                                                                                     
                                    
        

   
                                                                               
                            
    
                                             
     


                                                                                                      
                               
        






                                                                      
     


                                                                                                      
                               
        
   
 
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2003-2010, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id$


package scala.collection
package mutable

import generic._

/** <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>
 *
 *  @since 2.8
 */
trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
  extends MapLikeBase[A, B, This]
     with Builder[(A, B), This]
     with Growable[(A, B)]
     with Shrinkable[A]
     with Cloneable[This]
{ self =>

  import scala.collection.Traversable

  /** <p>
   *    A common implementation of <code>newBuilder</code> for all mutable maps
   *    in terms of <code>empty</code>.
   *  </p>
   *  <p>
   *    Overrides <code>MapLike</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); repr }

  /** 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 ++= repr

  /** The result when this map is used as a builder */
  def result: This = repr

  /** 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
    repr
  }

  /** 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)
    repr
  }


  /** 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)
    repr
  }
}