summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Rozendaal <erik@deler.org>2012-01-05 21:04:49 +0100
committerErik Rozendaal <erik@deler.org>2012-01-05 21:04:49 +0100
commit388ff4716f9f4162165221c42fb2f2aa83e1063c (patch)
tree1e91a4b6748506fde756f13b3a33d36973b4ddb6
parentd735d0f1d631942931765c793b983511359961e1 (diff)
downloadscala-388ff4716f9f4162165221c42fb2f2aa83e1063c.tar.gz
scala-388ff4716f9f4162165221c42fb2f2aa83e1063c.tar.bz2
scala-388ff4716f9f4162165221c42fb2f2aa83e1063c.zip
Add implementation notes. Consistently use eq/ne to compare with null.
-rw-r--r--src/library/scala/collection/immutable/RedBlack.scala31
1 files changed, 24 insertions, 7 deletions
diff --git a/src/library/scala/collection/immutable/RedBlack.scala b/src/library/scala/collection/immutable/RedBlack.scala
index 5729260cb2..30d3ff37a3 100644
--- a/src/library/scala/collection/immutable/RedBlack.scala
+++ b/src/library/scala/collection/immutable/RedBlack.scala
@@ -16,6 +16,11 @@ import annotation.meta.getter
/** An object containing the RedBlack tree implementation used by for `TreeMaps` and `TreeSets`.
*
+ * Implementation note: since efficiency is important for data structures this implementation
+ * uses <code>null</code> to represent empty trees. This also means pattern matching cannot
+ * easily be used. The API represented by the RedBlack object tries to hide these optimizations
+ * behind a reasonably clean API.
+ *
* @since 2.3
*/
private[immutable]
@@ -103,7 +108,7 @@ object RedBlack {
else
mkTree(isBlack, x, xv, a, r)
}
- private[this] def upd[A, B, B1 >: B](tree: Tree[A, B], k: A, v: B1)(implicit ordering: Ordering[A]): Tree[A, B1] = if (tree == null) {
+ private[this] def upd[A, B, B1 >: B](tree: Tree[A, B], k: A, v: B1)(implicit ordering: Ordering[A]): Tree[A, B1] = if (tree eq null) {
RedTree(k, v, null, null)
} else {
val cmp = ordering.compare(k, tree.key)
@@ -114,7 +119,7 @@ object RedBlack {
// Based on Stefan Kahrs' Haskell version of Okasaki's Red&Black Trees
// http://www.cse.unsw.edu.au/~dons/data/RedBlackTree.html
- private[this] def del[A, B](tree: Tree[A, B], k: A)(implicit ordering: Ordering[A]): Tree[A, B] = if (tree == null) null else {
+ private[this] def del[A, B](tree: Tree[A, B], k: A)(implicit ordering: Ordering[A]): Tree[A, B] = if (tree eq null) null else {
def balance(x: A, xv: B, tl: Tree[A, B], tr: Tree[A, B]) = if (isRedTree(tl)) {
if (isRedTree(tr)) {
RedTree(x, xv, tl.black, tr.black)
@@ -287,6 +292,15 @@ object RedBlack {
}
}
+ /*
+ * Forcing direct fields access using the @inline annotation helps speed up
+ * various operations (especially smallest/greatest and update/delete).
+ *
+ * Unfortunately the direct field access is not guaranteed to work (but
+ * works on the current implementation of the Scala compiler).
+ *
+ * An alternative is to implement the these classes using plain old Java code...
+ */
sealed abstract class Tree[A, +B](
@(inline @getter) final val key: A,
@(inline @getter) final val value: B,
@@ -355,11 +369,14 @@ object RedBlack {
index += 1
} catch {
case _: ArrayIndexOutOfBoundsException =>
- // Either the tree became unbalanced or we calculated the maximum height incorrectly.
- // To avoid crashing the iterator we expand the path array. Obviously this should never
- // happen...
- //
- // An exception handler is used instead of an if-condition to optimize the normal path.
+ /*
+ * Either the tree became unbalanced or we calculated the maximum height incorrectly.
+ * To avoid crashing the iterator we expand the path array. Obviously this should never
+ * happen...
+ *
+ * An exception handler is used instead of an if-condition to optimize the normal path.
+ * This makes a large difference in iteration speed!
+ */
assert(index >= path.length)
path :+= null
pushPath(tree)