第014講:Scala中Map和HashMap原始碼剖析及程式碼實踐(從1000個程式碼案例中學習人工智慧和大資料實戰)
阿新 • • 發佈:2018-12-25
第014講:Scala中Map和HashMap原始碼剖析及程式碼實踐
/** * A generic trait for immutable maps. Concrete classes have to provide * functionality for the abstract methods in `Map`: * * {{{ * def get(key: A): Option[B] * def iterator: Iterator[(A, B)] * def + [B1 >: B](kv: (A, B1)): Map[A, B1] * def -(key: A): Map[A, B] * }}} * * @since 1 */ trait Map[A, +B] extends Iterable[(A, B)] // with GenMap[A, B] with scala.collection.Map[A, B] with MapLike[A, B, Map[A, B]] { self => override def empty: Map[A, B] = Map.empty override def toMap[T, U](implicit ev: (A, B) <:< (T, U)): immutable.Map[T, U] = self.asInstanceOf[immutable.Map[T, U]]
/** Returns the value associated with a key, or a default value if the key is not contained in the map. * @param key the key. * @param default a computation that yields a default value in case no binding for `key` is * found in the map. * @tparam B1 the result type of the default computation. * @return the value associated with `key` if it exists, * otherwise the result of the `default` computation. * * @usecase def getOrElse(key: A, default: => B): B * @inheritdoc */ def getOrElse[B1 >: B](key: A, default: => B1): B1 = get(key) match { case Some(v) => v case None => default }
package scala.collection package mutable import generic._ import scala.collection.parallel.mutable.ParHashMap /** This class implements mutable maps using a hashtable. * * @since 1 * @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#hash_tables "Scala's Collection Library overview"]] * section on `Hash Tables` for more information. * * @tparam A the type of the keys contained in this hash map. * @tparam B the type of the values assigned to keys in this hash map. * * @define Coll `mutable.HashMap` * @define coll mutable hash map * @define thatinfo the class of the returned collection. In the standard library configuration, * `That` is always `HashMap[A, B]` if the elements contained in the resulting collection are * pairs of type `(A, B)`. This is because an implicit of type `CanBuildFrom[HashMap, (A, B), HashMap[A, B]]` * is defined in object `HashMap`. Otherwise, `That` resolves to the most specific type that doesn't have * to contain pairs of type `(A, B)`, which is `Iterable`. * @define bfinfo an implicit value of class `CanBuildFrom` which determines the * result class `That` from the current representation type `Repr` * and the new element type `B`. This is usually the `canBuildFrom` value * defined in object `HashMap`. * @define mayNotTerminateInf * @define willNotTerminateInf */ @SerialVersionUID(1L) class HashMap[A, B] private[collection] (contents: HashTable.Contents[A, DefaultEntry[A, B]]) extends AbstractMap[A, B] with Map[A, B] with MapLike[A, B, HashMap[A, B]] with HashTable[A, DefaultEntry[A, B]] with CustomParallelizable[(A, B), ParHashMap[A, B]] with Serializable { initWithContents(contents) type Entry = DefaultEntry[A, B] override def empty: HashMap[A, B] = HashMap.empty[A, B] override def clear() { clearTable() } override def size: Int = tableSize def this() = this(null) override def par = new ParHashMap[A, B](hashTableContents) // contains and apply overridden to avoid option allocations. override def contains(key: A): Boolean = findEntry(key) != null override def apply(key: A): B = { val result = findEntry(key) if (result eq null) default(key) else result.value } def get(key: A): Option[B] = { val e = findEntry(key) if (e eq null) None else Some(e.value) } override def put(key: A, value: B): Option[B] = { val e = findOrAddEntry(key, value) if (e eq null) None else { val v = e.value; e.value = value; Some(v) } } override def update(key: A, value: B): Unit = put(key, value) override def remove(key: A): Option[B] = { val e = removeEntry(key) if (e ne null) Some(e.value) else None } def += (kv: (A, B)): this.type = { val e = findOrAddEntry(kv._1, kv._2) if (e ne null) e.value = kv._2 this } def -=(key: A): this.type = { removeEntry(key); this } def iterator = entriesIterator map {e => (e.key, e.value)} override def foreach[C](f: ((A, B)) => C): Unit = foreachEntry(e => f(e.key, e.value)) /* Override to avoid tuple allocation in foreach */ override def keySet: scala.collection.Set[A] = new DefaultKeySet { override def foreach[C](f: A => C) = foreachEntry(e => f(e.key)) } /* Override to avoid tuple allocation in foreach */ override def values: scala.collection.Iterable[B] = new DefaultValuesIterable { override def foreach[C](f: B => C) = foreachEntry(e => f(e.value)) } /* Override to avoid tuple allocation */ override def keysIterator: Iterator[A] = new AbstractIterator[A] { val iter = entriesIterator def hasNext = iter.hasNext def next() = iter.next.key } /* Override to avoid tuple allocation */ override def valuesIterator: Iterator[B] = new AbstractIterator[B] { val iter = entriesIterator def hasNext = iter.hasNext def next() = iter.next.value } /** Toggles whether a size map is used to track hash map statistics. */ def useSizeMap(t: Boolean) = if (t) { if (!isSizeMapDefined) sizeMapInitAndRebuild } else sizeMapDisable protected def createNewEntry[B1](key: A, value: B1): Entry = { new Entry(key, value.asInstanceOf[B]) } private def writeObject(out: java.io.ObjectOutputStream) { serializeTo(out, { entry => out.writeObject(entry.key) out.writeObject(entry.value) }) } private def readObject(in: java.io.ObjectInputStream) { init(in, createNewEntry(in.readObject().asInstanceOf[A], in.readObject())) } } /** $factoryInfo * @define Coll `mutable.HashMap` * @define coll mutable hash map */ object HashMap extends MutableMapFactory[HashMap] { implicit def canBuildFrom[A, B]: CanBuildFrom[Coll, (A, B), HashMap[A, B]] = new MapCanBuildFrom[A, B] def empty[A, B]: HashMap[A, B] = new HashMap[A, B] }