@@ -11,8 +11,7 @@ package collection
11
11
package mutable
12
12
13
13
import generic ._
14
- import scala .collection .immutable .{RedBlackTree => RB }
15
- import scala .runtime .ObjectRef
14
+ import scala .collection .mutable .{RedBlackTree => RB }
16
15
17
16
/**
18
17
* @define Coll `mutable.TreeSet`
@@ -29,88 +28,162 @@ object TreeSet extends MutableSortedSetFactory[TreeSet] {
29
28
*/
30
29
def empty [A ](implicit ordering : Ordering [A ]) = new TreeSet [A ]()
31
30
31
+ /** $sortedMapCanBuildFromInfo */
32
+ implicit def canBuildFrom [A ](implicit ord : Ordering [A ]): CanBuildFrom [Coll , A , TreeSet [A ]] =
33
+ new SortedSetCanBuildFrom [A ]
32
34
}
33
35
34
36
/**
35
- * A mutable SortedSet using an immutable RedBlack Tree as underlying data structure.
37
+ * A mutable sorted set implemented using a mutable red-black tree as underlying data structure.
36
38
*
37
- * @author Lucien Pereira
39
+ * @param ordering the implicit ordering used to compare objects of type `A`.
40
+ * @tparam A the type of the keys contained in this tree set.
41
+ *
42
+ * @author Rui Gonçalves
43
+ * @version 2.12
44
+ * @since 2.10
38
45
*
46
+ * @define Coll mutable.TreeSet
47
+ * @define coll mutable tree set
39
48
*/
40
- @ deprecatedInheritance(" TreeSet is not designed to enable meaningful subclassing." , " 2.11.0" )
41
- class TreeSet [A ] private (treeRef : ObjectRef [RB .Tree [A , Null ]], from : Option [A ], until : Option [A ])(implicit val ordering : Ordering [A ])
42
- extends SortedSet [A ] with SetLike [A , TreeSet [A ]]
43
- with SortedSetLike [A , TreeSet [A ]] with Set [A ] with Serializable {
49
+ // Original API designed in part by Lucien Pereira
50
+ @ SerialVersionUID (- 3642111301929493640L )
51
+ sealed class TreeSet [A ] private (tree : RB .Tree [A , Null ])(implicit val ordering : Ordering [A ])
52
+ extends AbstractSortedSet [A ]
53
+ with SortedSet [A ]
54
+ with SetLike [A , TreeSet [A ]]
55
+ with SortedSetLike [A , TreeSet [A ]]
56
+ with Serializable {
44
57
45
58
if (ordering eq null )
46
59
throw new NullPointerException (" ordering must not be null" )
47
60
48
- def this ()(implicit ordering : Ordering [A ]) = this (new ObjectRef (null ), None , None )
61
+ /**
62
+ * Creates an empty `TreeSet`.
63
+ * @param ord the implicit ordering used to compare objects of type `A`.
64
+ * @return an empty `TreeSet`.
65
+ */
66
+ def this ()(implicit ord : Ordering [A ]) = this (RB .Tree .empty)(ord)
49
67
50
- override def size : Int = RB .countInRange(treeRef.elem, from, until)
68
+ override def empty = TreeSet .empty
69
+ override protected [this ] def newBuilder = TreeSet .newBuilder[A ]
51
70
52
- override def stringPrefix = " TreeSet"
71
+ /**
72
+ * Creates a ranged projection of this set. Any mutations in the ranged projection affect will update the original set
73
+ * and vice versa.
74
+ *
75
+ * Only keys between this projection's key range will ever appear as elements of this set, independently of whether
76
+ * the elements are added through the original set or through this view. That means that if one inserts an element in
77
+ * a view whose key is outside the view's bounds, calls to `contains` will _not_ consider the newly added element.
78
+ * Mutations are always reflected in the original set, though.
79
+ *
80
+ * @param from the lower bound (inclusive) of this projection wrapped in a `Some`, or `None` if there is no lower
81
+ * bound.
82
+ * @param until the upper bound (exclusive) of this projection wrapped in a `Some`, or `None` if there is no upper
83
+ * bound.
84
+ */
85
+ def rangeImpl (from : Option [A ], until : Option [A ]): TreeSet [A ] = new TreeSetView (from, until)
53
86
54
- override def empty : TreeSet [A ] = TreeSet .empty
87
+ def -= (key : A ): this .type = { RB .delete(tree, key); this }
88
+ def += (elem : A ): this .type = { RB .insert(tree, elem, null ); this }
55
89
56
- private def pickBound (comparison : (A , A ) => A , oldBound : Option [A ], newBound : Option [A ]) = (newBound, oldBound) match {
57
- case (Some (newB), Some (oldB)) => Some (comparison(newB, oldB))
58
- case (None , _) => oldBound
59
- case _ => newBound
60
- }
90
+ def contains (elem : A ) = RB .contains(tree, elem)
61
91
62
- override def rangeImpl ( fromArg : Option [ A ], untilArg : Option [ A ]) : TreeSet [ A ] = {
63
- val newFrom = pickBound(ordering.max, fromArg, from )
64
- val newUntil = pickBound(ordering.min, untilArg, until )
92
+ def iterator = RB .keysIterator(tree)
93
+ def keysIteratorFrom ( start : A ) = RB .keysIterator(tree, Some (start) )
94
+ override def iteratorFrom ( start : A ) = RB .keysIterator(tree, Some (start) )
65
95
66
- new TreeSet (treeRef, newFrom, newUntil )
67
- }
96
+ override def size = RB .size(tree )
97
+ override def isEmpty = RB .isEmpty(tree)
68
98
69
- override def -= ( elem : A ) : this . type = {
70
- treeRef.elem = RB .delete(treeRef.elem, elem )
71
- this
72
- }
99
+ override def head = RB .minKey(tree).get
100
+ override def headOption = RB .minKey(tree )
101
+ override def last = RB .maxKey(tree).get
102
+ override def lastOption = RB .maxKey(tree)
73
103
74
- override def += ( elem : A ): this . type = {
75
- treeRef.elem = RB .update(treeRef.elem, elem, null , overwrite = false )
76
- this
77
- }
104
+ override def foreach [ U ]( f : A => U ): Unit = RB .foreachKey(tree, f)
105
+ override def clear () : Unit = RB .clear(tree )
106
+
107
+ override def stringPrefix = " TreeSet "
78
108
79
109
/**
80
- * Thanks to the immutable nature of the
81
- * underlying Tree, we can share it with
82
- * the clone. So clone complexity in time is O(1).
110
+ * A ranged projection of a [[TreeSet ]]. Mutations on this set affect the original set and vice versa.
83
111
*
112
+ * Only keys between this projection's key range will ever appear as elements of this set, independently of whether
113
+ * the elements are added through the original set or through this view. That means that if one inserts an element in
114
+ * a view whose key is outside the view's bounds, calls to `contains` will _not_ consider the newly added element.
115
+ * Mutations are always reflected in the original set, though.
116
+ *
117
+ * @param from the lower bound (inclusive) of this projection wrapped in a `Some`, or `None` if there is no lower
118
+ * bound.
119
+ * @param until the upper bound (exclusive) of this projection wrapped in a `Some`, or `None` if there is no upper
120
+ * bound.
84
121
*/
85
- override def clone (): TreeSet [A ] =
86
- new TreeSet [A ](new ObjectRef (treeRef.elem), from, until)
87
-
88
- private val notProjection = ! (from.isDefined || until.isDefined)
122
+ @ SerialVersionUID (7087824939194006086L )
123
+ private [this ] final class TreeSetView (from : Option [A ], until : Option [A ]) extends TreeSet [A ](tree) {
124
+
125
+ /**
126
+ * Given a possible new lower bound, chooses and returns the most constraining one (the maximum).
127
+ */
128
+ private [this ] def pickLowerBound (newFrom : Option [A ]): Option [A ] = (from, newFrom) match {
129
+ case (Some (fr), Some (newFr)) => Some (ordering.max(fr, newFr))
130
+ case (None , _) => newFrom
131
+ case _ => from
132
+ }
89
133
90
- override def contains (elem : A ): Boolean = {
91
- def leftAcceptable : Boolean = from match {
92
- case Some (lb) => ordering.gteq(elem, lb)
93
- case _ => true
134
+ /**
135
+ * Given a possible new upper bound, chooses and returns the most constraining one (the minimum).
136
+ */
137
+ private [this ] def pickUpperBound (newUntil : Option [A ]): Option [A ] = (until, newUntil) match {
138
+ case (Some (unt), Some (newUnt)) => Some (ordering.min(unt, newUnt))
139
+ case (None , _) => newUntil
140
+ case _ => until
94
141
}
95
142
96
- def rightAcceptable : Boolean = until match {
97
- case Some (ub) => ordering.lt(elem, ub)
98
- case _ => true
143
+ /**
144
+ * Returns true if the argument is inside the view bounds (between `from` and `until`).
145
+ */
146
+ private [this ] def isInsideViewBounds (key : A ): Boolean = {
147
+ val afterFrom = from.isEmpty || ordering.compare(from.get, key) <= 0
148
+ val beforeUntil = until.isEmpty || ordering.compare(key, until.get) < 0
149
+ afterFrom && beforeUntil
99
150
}
100
151
101
- (notProjection || (leftAcceptable && rightAcceptable)) &&
102
- RB .contains(treeRef.elem, elem)
103
- }
152
+ override def rangeImpl (from : Option [A ], until : Option [A ]): TreeSet [A ] =
153
+ new TreeSetView (pickLowerBound(from), pickUpperBound(until))
154
+
155
+ override def contains (key : A ) = isInsideViewBounds(key) && RB .contains(tree, key)
156
+
157
+ override def iterator = RB .keysIterator(tree, from, until)
158
+ override def keysIteratorFrom (start : A ) = RB .keysIterator(tree, pickLowerBound(Some (start)), until)
159
+ override def iteratorFrom (start : A ) = RB .keysIterator(tree, pickLowerBound(Some (start)), until)
104
160
105
- override def iterator : Iterator [A ] = iteratorFrom(None )
161
+ override def size = iterator.length
162
+ override def isEmpty = ! iterator.hasNext
106
163
107
- override def keysIteratorFrom (start : A ) = iteratorFrom(Some (start))
164
+ override def head = headOption.get
165
+ override def headOption = {
166
+ val elem = if (from.isDefined) RB .minKeyAfter(tree, from.get) else RB .minKey(tree)
167
+ (elem, until) match {
168
+ case (Some (e), Some (unt)) if ordering.compare(e, unt) >= 0 => None
169
+ case _ => elem
170
+ }
171
+ }
108
172
109
- private def iteratorFrom (start : Option [A ]) = {
110
- val it = RB .keysIterator(treeRef.elem, pickBound(ordering.max, from, start))
111
- until match {
112
- case None => it
113
- case Some (ub) => it takeWhile (k => ordering.lt(k, ub))
173
+ override def last = lastOption.get
174
+ override def lastOption = {
175
+ val elem = if (until.isDefined) RB .maxKeyBefore(tree, until.get) else RB .maxKey(tree)
176
+ (elem, from) match {
177
+ case (Some (e), Some (fr)) if ordering.compare(e, fr) < 0 => None
178
+ case _ => elem
179
+ }
114
180
}
181
+
182
+ // Using the iterator should be efficient enough; if performance is deemed a problem later, a specialized
183
+ // `foreachKey(f, from, until)` method can be created in `RedBlackTree`. See
184
+ // https://github.com/scala/scala/pull/4608#discussion_r34307985 for a discussion about this.
185
+ override def foreach [U ](f : A => U ): Unit = iterator.foreach(f)
186
+
187
+ override def clone () = super .clone().rangeImpl(from, until)
115
188
}
116
189
}
0 commit comments