Skip to content

Commit e271e91

Browse files
committed
Clone scala/collection/immutable/TreeSet.scala
1 parent 9477213 commit e271e91

File tree

1 file changed

+296
-0
lines changed

1 file changed

+296
-0
lines changed
Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala
14+
package collection
15+
package immutable
16+
17+
import scala.collection.Stepper.EfficientSplit
18+
import scala.collection.generic.DefaultSerializable
19+
import scala.collection.mutable.ReusableBuilder
20+
import scala.collection.immutable.{RedBlackTree => RB}
21+
import scala.runtime.AbstractFunction1
22+
23+
24+
/** This class implements immutable sorted sets using a tree.
25+
*
26+
* @tparam A the type of the elements contained in this tree set
27+
* @param ordering the implicit ordering used to compare objects of type `A`
28+
*
29+
* @see [[https://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#red-black-trees "Scala's Collection Library overview"]]
30+
* section on `Red-Black Trees` for more information.
31+
*
32+
* @define Coll `immutable.TreeSet`
33+
* @define coll immutable tree set
34+
* @define orderDependent
35+
* @define orderDependentFold
36+
* @define mayNotTerminateInf
37+
* @define willNotTerminateInf
38+
*/
39+
final class TreeSet[A] private[immutable] (private[immutable] val tree: RB.Tree[A, Any])(implicit val ordering: Ordering[A])
40+
extends AbstractSet[A]
41+
with SortedSet[A]
42+
with SortedSetOps[A, TreeSet, TreeSet[A]]
43+
with StrictOptimizedSortedSetOps[A, TreeSet, TreeSet[A]]
44+
with SortedSetFactoryDefaults[A, TreeSet, Set]
45+
with DefaultSerializable {
46+
47+
if (ordering eq null) throw new NullPointerException("ordering must not be null")
48+
49+
def this()(implicit ordering: Ordering[A]) = this(null)(ordering)
50+
51+
override def sortedIterableFactory = TreeSet
52+
53+
private[this] def newSetOrSelf(t: RB.Tree[A, Any]) = if(t eq tree) this else new TreeSet[A](t)
54+
55+
override def size: Int = RB.count(tree)
56+
57+
override def isEmpty = size == 0
58+
59+
override def head: A = RB.smallest(tree).key
60+
61+
override def last: A = RB.greatest(tree).key
62+
63+
override def tail: TreeSet[A] = new TreeSet(RB.tail(tree))
64+
65+
override def init: TreeSet[A] = new TreeSet(RB.init(tree))
66+
67+
override def min[A1 >: A](implicit ord: Ordering[A1]): A = {
68+
if ((ord eq ordering) && nonEmpty) {
69+
head
70+
} else {
71+
super.min(ord)
72+
}
73+
}
74+
75+
override def max[A1 >: A](implicit ord: Ordering[A1]): A = {
76+
if ((ord eq ordering) && nonEmpty) {
77+
last
78+
} else {
79+
super.max(ord)
80+
}
81+
}
82+
83+
override def drop(n: Int): TreeSet[A] = {
84+
if (n <= 0) this
85+
else if (n >= size) empty
86+
else new TreeSet(RB.drop(tree, n))
87+
}
88+
89+
override def take(n: Int): TreeSet[A] = {
90+
if (n <= 0) empty
91+
else if (n >= size) this
92+
else new TreeSet(RB.take(tree, n))
93+
}
94+
95+
override def slice(from: Int, until: Int): TreeSet[A] = {
96+
if (until <= from) empty
97+
else if (from <= 0) take(until)
98+
else if (until >= size) drop(from)
99+
else new TreeSet(RB.slice(tree, from, until))
100+
}
101+
102+
override def dropRight(n: Int): TreeSet[A] = take(size - math.max(n, 0))
103+
104+
override def takeRight(n: Int): TreeSet[A] = drop(size - math.max(n, 0))
105+
106+
private[this] def countWhile(p: A => Boolean): Int = {
107+
var result = 0
108+
val it = iterator
109+
while (it.hasNext && p(it.next())) result += 1
110+
result
111+
}
112+
override def dropWhile(p: A => Boolean): TreeSet[A] = drop(countWhile(p))
113+
114+
override def takeWhile(p: A => Boolean): TreeSet[A] = take(countWhile(p))
115+
116+
override def span(p: A => Boolean): (TreeSet[A], TreeSet[A]) = splitAt(countWhile(p))
117+
118+
override def foreach[U](f: A => U): Unit = RB.foreachKey(tree, f)
119+
120+
override def minAfter(key: A): Option[A] = {
121+
val v = RB.minAfter(tree, key)
122+
if (v eq null) Option.empty else Some(v.key)
123+
}
124+
125+
override def maxBefore(key: A): Option[A] = {
126+
val v = RB.maxBefore(tree, key)
127+
if (v eq null) Option.empty else Some(v.key)
128+
}
129+
130+
def iterator: Iterator[A] = RB.keysIterator(tree)
131+
132+
def iteratorFrom(start: A): Iterator[A] = RB.keysIterator(tree, Some(start))
133+
134+
override def stepper[S <: Stepper[_]](implicit shape: StepperShape[A, S]): S with EfficientSplit = {
135+
import scala.collection.convert.impl._
136+
type T = RB.Tree[A, Any]
137+
val s = shape.shape match {
138+
case StepperShape.IntShape => IntBinaryTreeStepper.from[T] (size, tree, _.left, _.right, _.key.asInstanceOf[Int])
139+
case StepperShape.LongShape => LongBinaryTreeStepper.from[T] (size, tree, _.left, _.right, _.key.asInstanceOf[Long])
140+
case StepperShape.DoubleShape => DoubleBinaryTreeStepper.from[T](size, tree, _.left, _.right, _.key.asInstanceOf[Double])
141+
case _ => shape.parUnbox(AnyBinaryTreeStepper.from[A, T](size, tree, _.left, _.right, _.key))
142+
}
143+
s.asInstanceOf[S with EfficientSplit]
144+
}
145+
146+
/** Checks if this set contains element `elem`.
147+
*
148+
* @param elem the element to check for membership.
149+
* @return true, iff `elem` is contained in this set.
150+
*/
151+
def contains(elem: A): Boolean = RB.contains(tree, elem)
152+
153+
override def range(from: A, until: A): TreeSet[A] = newSetOrSelf(RB.range(tree, from, until))
154+
155+
def rangeImpl(from: Option[A], until: Option[A]): TreeSet[A] = newSetOrSelf(RB.rangeImpl(tree, from, until))
156+
157+
/** Creates a new `TreeSet` with the entry added.
158+
*
159+
* @param elem a new element to add.
160+
* @return a new $coll containing `elem` and all the elements of this $coll.
161+
*/
162+
def incl(elem: A): TreeSet[A] =
163+
newSetOrSelf(RB.update(tree, elem, null, overwrite = false))
164+
165+
/** Creates a new `TreeSet` with the entry removed.
166+
*
167+
* @param elem a new element to add.
168+
* @return a new $coll containing all the elements of this $coll except `elem`.
169+
*/
170+
def excl(elem: A): TreeSet[A] =
171+
newSetOrSelf(RB.delete(tree, elem))
172+
173+
override def concat(that: collection.IterableOnce[A]): TreeSet[A] = {
174+
val t = that match {
175+
case ts: TreeSet[A] if ordering == ts.ordering =>
176+
RB.union(tree, ts.tree)
177+
case _ =>
178+
val it = that.iterator
179+
var t = tree
180+
while (it.hasNext) t = RB.update(t, it.next(), null, overwrite = false)
181+
t
182+
}
183+
newSetOrSelf(t)
184+
}
185+
186+
override def removedAll(that: IterableOnce[A]): TreeSet[A] = that match {
187+
case ts: TreeSet[A] if ordering == ts.ordering =>
188+
newSetOrSelf(RB.difference(tree, ts.tree))
189+
case _ =>
190+
//TODO add an implementation of a mutable subtractor similar to TreeMap
191+
//but at least this doesn't create a TreeSet for each iteration
192+
object sub extends AbstractFunction1[A, Unit] {
193+
var currentTree = tree
194+
override def apply(k: A): Unit = {
195+
currentTree = RB.delete(currentTree, k)
196+
}
197+
}
198+
that.iterator.foreach(sub)
199+
newSetOrSelf(sub.currentTree)
200+
}
201+
202+
override def intersect(that: collection.Set[A]): TreeSet[A] = that match {
203+
case ts: TreeSet[A] if ordering == ts.ordering =>
204+
newSetOrSelf(RB.intersect(tree, ts.tree))
205+
case _ =>
206+
super.intersect(that)
207+
}
208+
209+
override def diff(that: collection.Set[A]): TreeSet[A] = that match {
210+
case ts: TreeSet[A] if ordering == ts.ordering =>
211+
newSetOrSelf(RB.difference(tree, ts.tree))
212+
case _ =>
213+
super.diff(that)
214+
}
215+
216+
override def filter(f: A => Boolean): TreeSet[A] = newSetOrSelf(RB.filterEntries[A, Any](tree, {(k, _) => f(k)}))
217+
218+
override def partition(p: A => Boolean): (TreeSet[A], TreeSet[A]) = {
219+
val (l, r) = RB.partitionEntries(tree, {(a:A, _: Any) => p(a)})
220+
(newSetOrSelf(l), newSetOrSelf(r))
221+
}
222+
223+
override def equals(obj: Any): Boolean = obj match {
224+
case that: TreeSet[A @unchecked] if ordering == that.ordering => RB.keysEqual(tree, that.tree)
225+
case _ => super.equals(obj)
226+
}
227+
228+
override protected[this] def className = "TreeSet"
229+
}
230+
231+
/**
232+
* $factoryInfo
233+
*
234+
* @define Coll `immutable.TreeSet`
235+
* @define coll immutable tree set
236+
*/
237+
@SerialVersionUID(3L)
238+
object TreeSet extends SortedIterableFactory[TreeSet] {
239+
240+
def empty[A: Ordering]: TreeSet[A] = new TreeSet[A]
241+
242+
def from[E](it: scala.collection.IterableOnce[E])(implicit ordering: Ordering[E]): TreeSet[E] =
243+
it match {
244+
case ts: TreeSet[E] if ordering == ts.ordering => ts
245+
case ss: scala.collection.SortedSet[E] if ordering == ss.ordering =>
246+
new TreeSet[E](RB.fromOrderedKeys(ss.iterator, ss.size))
247+
case r: Range if (ordering eq Ordering.Int) || (Ordering.Int isReverseOf ordering) =>
248+
val it = if((ordering eq Ordering.Int) == (r.step > 0)) r.iterator else r.reverseIterator
249+
val tree = RB.fromOrderedKeys(it.asInstanceOf[Iterator[E]], r.size)
250+
// The cast is needed to compile with Dotty:
251+
// Dotty doesn't infer that E =:= Int, since instantiation of covariant GADTs is unsound
252+
new TreeSet[E](tree)
253+
case _ =>
254+
var t: RB.Tree[E, Null] = null
255+
val i = it.iterator
256+
while (i.hasNext) t = RB.update(t, i.next(), null, overwrite = false)
257+
new TreeSet[E](t)
258+
}
259+
260+
def newBuilder[A](implicit ordering: Ordering[A]): ReusableBuilder[A, TreeSet[A]] = new TreeSetBuilder[A]
261+
private class TreeSetBuilder[A](implicit ordering: Ordering[A])
262+
extends RB.SetHelper[A]
263+
with ReusableBuilder[A, TreeSet[A]] {
264+
type Tree = RB.Tree[A, Any]
265+
private [this] var tree:RB.Tree[A, Any] = null
266+
267+
override def addOne(elem: A): this.type = {
268+
tree = mutableUpd(tree, elem)
269+
this
270+
}
271+
272+
override def addAll(xs: IterableOnce[A]): this.type = {
273+
xs match {
274+
// TODO consider writing a mutable-safe union for TreeSet/TreeMap builder ++=
275+
// for the moment we have to force immutability before the union
276+
// which will waste some time and space
277+
// calling `beforePublish` makes `tree` immutable
278+
case ts: TreeSet[A] if ts.ordering == ordering =>
279+
if (tree eq null) tree = ts.tree
280+
else tree = RB.union(beforePublish(tree), ts.tree)(ordering)
281+
case ts: TreeMap[A @unchecked, _] if ts.ordering == ordering =>
282+
if (tree eq null) tree = ts.tree0
283+
else tree = RB.union(beforePublish(tree), ts.tree0)(ordering)
284+
case _ =>
285+
super.addAll(xs)
286+
}
287+
this
288+
}
289+
290+
override def clear(): Unit = {
291+
tree = null
292+
}
293+
294+
override def result(): TreeSet[A] = new TreeSet[A](beforePublish(tree))(ordering)
295+
}
296+
}

0 commit comments

Comments
 (0)