Skip to content

Commit e8da942

Browse files
committed
more ++ and -- implementation for TreeSet and TreeMap into respective classes
provide a simple implementation of addAll for TreMap ad TreeSet
1 parent bd67c1b commit e8da942

File tree

3 files changed

+61
-18
lines changed

3 files changed

+61
-18
lines changed

library/src/scala/collection/generic/Subtractable.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ trait Subtractable[A, +Repr <: Subtractable[A, Repr]] { self =>
6464
def --(xs: GenTraversableOnce[A]): Repr = this match {
6565
case hs: HashSet[A] if xs.isInstanceOf[HashSet[A]] =>
6666
hs.diff(xs.asInstanceOf[HashSet[A]]).asInstanceOf[Repr]
67-
case ts: TreeMap[A, _] if xs.isInstanceOf[TreeSet[A]] && ts.ordering == xs.asInstanceOf[TreeSet[A]].ordering =>
68-
ts.removeAllImpl(xs.asInstanceOf[TreeSet[A]]).asInstanceOf[Repr]
69-
case ts: TreeSet[A] if xs.isInstanceOf[TreeSet[A]] && ts.ordering == xs.asInstanceOf[TreeSet[A]].ordering =>
70-
ts.removeAll(xs.asInstanceOf[TreeSet[A]]).asInstanceOf[Repr]
67+
case ts: TreeMap[A, _] =>
68+
ts.removeAllImpl(xs).asInstanceOf[Repr]
69+
case ts: TreeSet[A] =>
70+
ts.removeAll(xs).asInstanceOf[Repr]
7171
case _ =>
7272
(repr /: xs.seq) (_ - _)
7373
}

library/src/scala/collection/immutable/TreeMap.scala

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import java.io.IOException
1919
import generic._
2020
import immutable.{NewRedBlackTree => RB}
2121
import mutable.Builder
22-
import scala.runtime.AbstractFunction2
22+
import scala.annotation.tailrec
23+
import scala.runtime.{AbstractFunction1, AbstractFunction2}
2324
import scala.util.hashing.MurmurHash3
2425

2526
/** $factoryInfo
@@ -268,18 +269,36 @@ final class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering:
268269
xs match {
269270
case tm: TreeMap[A, B] if ordering == tm.ordering =>
270271
newMapOrSelf(RB.union(tree, tm.tree0))
272+
case ls: LinearSeq[(A,B1)] =>
273+
if (ls.isEmpty) this //to avoid the creation of the adder
274+
else {
275+
val adder = new Adder[B1]
276+
adder addAll ls
277+
newMapOrSelf(adder.finalTree)
278+
}
271279
case _ =>
272-
// probably should be something like
273-
// val builder = TreeMap.newBuilder[A, B1]
274-
// builder ++= this
275-
// builder ++= xs
276-
// builder.result()
277-
//but for compat and simplicity
278-
279-
((repr: TreeMap[A, B1]) /: xs.seq) (_ + _)
280+
val adder = new Adder[B1]
281+
xs foreach adder
282+
newMapOrSelf(adder.finalTree)
283+
}
284+
}
285+
private final class Adder[B1 >: B]
286+
extends RB.MapHelper[A, B1] with Function1[(A, B1), Unit] {
287+
private var currentMutableTree: RB.Tree[A,B1] = tree0
288+
def finalTree = beforePublish(currentMutableTree)
289+
override def apply(kv: (A, B1)): Unit = {
290+
currentMutableTree= mutableUpd(currentMutableTree, kv._1, kv._2)
291+
}
292+
@tailrec def addAll(ls: LinearSeq[(A, B1)]): Unit = {
293+
if (!ls.isEmpty) {
294+
val kv = ls.head
295+
currentMutableTree = mutableUpd(currentMutableTree, kv._1, kv._2)
296+
addAll(ls.tail)
297+
}
280298
}
281299
}
282300

301+
283302
/** A new TreeMap with the entry added is returned,
284303
* assuming that key is <em>not</em> in the TreeMap.
285304
*
@@ -296,11 +315,23 @@ final class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering:
296315
def - (key:A): TreeMap[A, B] =
297316
newMapOrSelf(RB.delete(tree, key))
298317

299-
private[collection] def removeAllImpl(ts: TreeSet[A]): TreeMap[A, B] = {
300-
assert(ordering == ts.ordering)
301-
newMapOrSelf(RB.difference(tree, ts.tree))
318+
private[collection] def removeAllImpl(xs: GenTraversableOnce[A]): TreeMap[A, B] = xs match {
319+
case ts: TreeSet[A] if ordering == ts.ordering =>
320+
newMapOrSelf(RB.difference(tree, ts.tree))
321+
case _ =>
322+
//TODO add an implementation of a mutable subtractor similar to ++
323+
//but at least this doesnt create a TreeMap for each iteration
324+
object sub extends AbstractFunction1[A, Unit] {
325+
var currentTree = tree0
326+
override def apply(k: A): Unit = {
327+
currentTree=RB.delete(currentTree, k)
328+
}
329+
}
330+
xs.foreach(sub)
331+
newMapOrSelf(sub.currentTree)
302332
}
303333

334+
304335
/** Check if this map maps `key` to a value and return the
305336
* value if it exists.
306337
*

library/src/scala/collection/immutable/TreeSet.scala

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import java.io.IOException
1919
import generic._
2020
import immutable.{NewRedBlackTree => RB}
2121
import mutable.Builder
22+
import scala.runtime.AbstractFunction1
2223

2324
/** $factoryInfo
2425
* @define Coll `immutable.TreeSet`
@@ -274,9 +275,20 @@ final class TreeSet[A] private[immutable] (private[immutable] val tree: RB.Tree[
274275
}
275276
}
276277

277-
private [collection] def removeAll(ts: TreeSet[A]): TreeSet[A] = {
278-
assert (ordering == ts.ordering)
278+
private [collection] def removeAll(xs : GenTraversableOnce[A]): TreeSet[A] = xs match {
279+
case ts: TreeSet[A] if ordering == ts.ordering =>
279280
newSetOrSelf(RB.difference(tree, ts.tree))
281+
case _ =>
282+
//TODO add an implementation of a mutable subtractor similar to TreeMap
283+
//but at least this doesn't create a TreeSet for each iteration
284+
object sub extends AbstractFunction1[A, Unit] {
285+
var currentTree = tree
286+
override def apply(k: A): Unit = {
287+
currentTree = RB.delete(tree, k)
288+
}
289+
}
290+
xs.foreach(sub)
291+
newSetOrSelf(sub.currentTree)
280292
}
281293

282294
override private[scala] def filterImpl(f: A => Boolean, isFlipped: Boolean) =

0 commit comments

Comments
 (0)