summaryrefslogtreecommitdiff
path: root/src/library/scala/collection/mutable/Map.scala
blob: e9b3a24d119f3e946ecfa2c86783e8f093ce3286 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2003-2008, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

// $Id$


package scala.collection.mutable

import Predef._


/** The canonical factory methods for <a href="Map.html">mutable maps</a>.
 *  These currently return <a href="HashMap.html">HashMap's</a>.
 */
object Map {

  /** The empty map of this type; this is implemented as a hashtable */
  def empty[A, B]: Map[A, B] = new HashMap[A, B]

  /** The canonical factory for this type
   */
  def apply[A, B](elems: (A, B)*) = empty[A, B] ++ elems
}

/** This trait represents mutable maps. Concrete map implementations
 *  just have to provide functionality for the abstract methods in
 *  <code>scala.collection.Map</code> as well as for <code>update</code>,
 *  and <code>-=</code>.
 *
 *  @author  Matthias Zenger
 *  @author  Martin Odersky
 *  @version 2.0, 31/12/2006
 */
@cloneable
trait Map[A, B] extends AnyRef
      with collection.Map[A, B]
      with Scriptable[Message[(A, B)]]
      with CloneableCollection
{
  /** This method allows one to add 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 by this
   *  function.
   *
   * @param key    The key to update
   * @param value  The new value
   */
  def update(key: A, value: B)

  /** Add a key/value pair to this map.
   *  @param    kv the key/value pair.
   */
  def += (kv: (A, B)) { update(kv._1, kv._2) }

  /** Add two or more key/value pairs to this map.
   *  @param    kv1 the first key/value pair.
   *  @param    kv2 the second key/value pair.
   *  @param    kvs the remaining key/value pairs.
   */
  def += (kv1: (A, B), kv2: (A, B), kvs: (A, B)*) {
    this += kv1; this += kv2; this ++= kvs
  }

  /** Add a sequence of key/value pairs to this map.
   *  @param    kvs the iterable object containing all key/value pairs.
   */
  def ++= (kvs: Iterable[(A, B)]) { this ++= kvs.elements }

  /** Add a sequence of key/value pairs to this map.
   *  @param    kvs the iterator containing all key/value pairs.
   */
  def ++= (kvs: Iterator[(A, B)]) { kvs foreach += }

  /** Add a key/value pair to this map.
   *  @param    kv the key/value pair.
   *  @return   The map itself with the new binding added in place.
   */
  def + (kv: (A, B)): Map[A, B] = { this += kv; this }

  /** Add two or more key/value pairs to this map.
   *  @param    kv1 the first key/value pair.
   *  @param    kv2 the second key/value pair.
   *  @param    kvs the remaining key/value pairs.
   *  @return   The map itself with the new bindings added in place.
   */
  def + (kv1: (A, B), kv2: (A, B), kvs: (A, B)*): Map[A, B] = {
    this.+=(kv1, kv2, kvs: _*); this
  }

  /** Add a sequence of key/value pairs to this map.
   *  @param    kvs the iterable object containing all key/value pairs.
   *  @return   The itself map with the new bindings added in place.
   */
  def ++ (kvs: Iterable[(A, B)]): Map[A, B] = { this ++= kvs; this }

  /** Add a sequence of key/value pairs to this map.
   *  @param    kvs the iterator containing all key/value pairs.
   *  @return   The itself map with the new bindings added in place.
   */
  def ++ (kvs: Iterator[(A, B)]): Map[A, B] = { this ++= kvs; this }

  /** Remove a key from this map, noop if key is not present.
   *  @param    key the key to be removed
   */
  def -= (key: A)

  /** Remove two or more keys from this map
   *  @param    key1 the first key to be removed
   *  @param    key2 the second key to be removed
   *  @param    keys the remaining keys to be removed
   */
  def -= (key1: A, key2: A, keys: A*) { this -= key1; this -= key2; this --= keys }

  /** Remove a sequence of keys from this map
   *  @param    keys the keys to be removed
   */
  def --= (keys: Iterable[A]) { this --= keys.elements }

  /** Remove a sequence of keys from this map
   *  @param    keys the keys to be removed
   */
  def --= (keys: Iterator[A]) { keys foreach -= }

  /** Remove a key from this map
   *  @param    key the key to be removed
   *  @return   The map itself with the binding for <code>key</code> removed if
   *            it existed.
   */
  def - (key: A): Map[A, B] = { this -= key; this }

  /** Remove <code>key</code> from this map and return the element
   *  that the key was previously mapped to (if any).
   */
  def removeKey(key: A): Option[B] = {
    val ret = get(key)
    this -= key
    ret
  }

  /** Map <code>key</code> to <code>elem</code> in this map and return the element
   *  that the key was previously mapped to (if any).
   */
  def put(key: A, elem: B): Option[B] = {
    val ret = get(key)
    this(key) = elem
    ret
  }

  /** Remove two or more keys from this map
   *  @param    key1 the first key to be removed
   *  @param    key2 the second key to be removed
   *  @param    keys the remaining keys to be removed
   *  @return   The map itself with all bindings for the given keys removed.
   */
  def - (key1: A, key2: A, keys: A*): Map[A, B] = { this.-=(key1, key2, keys: _*); this }

  /** Remove a sequence of keys from this map
   *  @param    keys the keys to be removed
   *  @return   The map itself with all bindings for <code>keys</code> removed.
   */
  def -- (keys: Iterable[A]): Map[A, B] = { this --= keys; this }

  /** Remove a sequence of keys from this map
   *  @param    keys the keys to be removed
   *  @return   The map itself with all bindings for <code>keys</code> removed.
   */
  def -- (keys: Iterator[A]): Map[A, B] = { this --= keys; this }

  /** Removes all mappings from the map. After this operation is
   *  completed, the map is empty.
   */
  def clear() { keys foreach -= }

  /** 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) {
    elements foreach {
      case (key, value) => update(key, f(key, value))
    }
  }

  /** This method retains 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 if retain in Iterable.
   */
  def retain(p: (A, B) => Boolean) {
    toList foreach {
      case (key, value) => if (!p(key, value)) -=(key)
    }
  }

  /** Send a message to this scriptable object.
   *
   *  @param cmd  the message to send.
   */
  def <<(cmd: Message[(A, B)]): Unit = cmd match {
    case Include((k, v)) => update(k, v)
    case Update((k, v)) => update(k, v)
    case Remove((k, _)) => this -= k
    case Reset() => clear
    case s: Script[_] => s.elements foreach <<
    case _ => throw new UnsupportedOperationException("message " + cmd + " not understood")
  }

  /** Return a clone of this map.
   *
   *  @return a map with the same elements.
   */
  override def clone(): Map[A, B] = super.clone().asInstanceOf[Map[A, B]]

  /** Return a read-only projection of this map */
  def readOnly: scala.collection.Map[A, B] = new scala.collection.Map[A, B] {
    override def toString = "ro-" + Map.this.toString
    override def size = Map.this.size
    override def elements = Map.this.elements
    override def get(key: A) = Map.this.get(key)
  }

  /** This method defines syntactic sugar for adding or modifying
   *  mappings. It is typically used in the following way:
   *  <pre>
   *  map += key -> value
   *  </pre>
   *  @deprecated   use <code>+= Pair(key, value)</code>
   */
  @deprecated
  def +=(key: A): MapTo = new MapTo(key)

  /** <code>incl</code> can be used to add many mappings at the same time
   *  to the map. The method assumes that a mapping is represented
   *  by a <code>Pair</code> object who's first component denotes the
   *  key, and who's second component refers to the value.
   *
   * @param mappings
   * @deprecated   use <code>+=</code>
   */
  @deprecated
  def incl(mappings: (A, B)*) { this ++= mappings.elements }

  /** This method will remove all the mappings for the given sequence
   *  of keys from the map.
   *
   * @param keys
   * @deprecated    use <code>-=</code>
   */
  @deprecated
  def excl(keys: A*) { this --= keys.elements }

  @deprecated
  class MapTo(key: A) {
    def ->(value: B) { update(key, value) }
  }

}