@@ -30,16 +30,18 @@ trait SeqView[+A] extends SeqOps[A, View, View[A]] with View[A] {
30
30
def concat [B >: A ](suffix : SeqView .SomeSeqOps [B ]): SeqView [B ] = new SeqView .Concat (this , suffix)
31
31
def appendedAll [B >: A ](suffix : SeqView .SomeSeqOps [B ]): SeqView [B ] = new SeqView .Concat (this , suffix)
32
32
def prependedAll [B >: A ](prefix : SeqView .SomeSeqOps [B ]): SeqView [B ] = new SeqView .Concat (prefix, this )
33
+
34
+ override def sorted [B >: A ](implicit ord : Ordering [B ]): SeqView [A ] = new SeqView .Sorted (this , ord)
33
35
}
34
36
35
37
object SeqView {
36
38
37
39
/** A `SeqOps` whose collection type and collection type constructor are unknown */
38
- type SomeSeqOps [+ A ] = SeqOps [A , AnyConstr , _]
40
+ private type SomeSeqOps [+ A ] = SeqOps [A , AnyConstr , _]
39
41
40
42
/** A view that doesn’t apply any transformation to an underlying sequence */
41
43
@ SerialVersionUID (3L )
42
- class Id [+ A ](underlying : SeqOps [ A , AnyConstr , _ ]) extends AbstractSeqView [A ] {
44
+ class Id [+ A ](underlying : SomeSeqOps [ A ]) extends AbstractSeqView [A ] {
43
45
def apply (idx : Int ): A = underlying.apply(idx)
44
46
def length : Int = underlying.length
45
47
def iterator : Iterator [A ] = underlying.iterator
@@ -115,6 +117,78 @@ object SeqView {
115
117
@ throws[IndexOutOfBoundsException ]
116
118
def apply (i : Int ) = underlying.apply(i)
117
119
}
120
+
121
+ @ SerialVersionUID (3L )
122
+ class Sorted [A , B >: A ](private [this ] var underlying : SomeSeqOps [A ], ord : Ordering [B ]) extends SeqView [A ] {
123
+ outer =>
124
+
125
+ @ SerialVersionUID (3L )
126
+ private [this ] class ReverseSorted extends SeqView [A ] {
127
+ private [this ] lazy val _reversed = new SeqView .Reverse (_sorted)
128
+
129
+ def apply (i : Int ): A = _reversed.apply(i)
130
+ def length : Int = elems.length
131
+ def iterator : Iterator [A ] = Iterator .empty ++ _reversed.iterator // very lazy
132
+ override def knownSize : Int = elems.knownSize
133
+ override def isEmpty : Boolean = elems.isEmpty
134
+ override def to [C1 ](factory : Factory [A , C1 ]): C1 = _reversed.to(factory)
135
+ override def reverse : SeqView [A ] = outer
136
+ override protected def reversed : Iterable [A ] = outer
137
+
138
+ override def sorted [B1 >: A ](implicit ord1 : Ordering [B1 ]): SeqView [A ] =
139
+ if (ord1 == Sorted .this .ord) outer
140
+ else if (ord1.isReverseOf(Sorted .this .ord)) this
141
+ else new Sorted (elems, ord1)
142
+ }
143
+
144
+ @ volatile private [this ] var evaluated = false
145
+
146
+ private [this ] lazy val _sorted : Seq [A ] = {
147
+ val res = {
148
+ val len = underlying.length
149
+ if (len == 0 ) Nil
150
+ else if (len == 1 ) List (underlying.head)
151
+ else {
152
+ val arr = new Array [Any ](len) // Array[Any] =:= Array[AnyRef]
153
+ underlying.copyToArray(arr)
154
+ java.util.Arrays .sort(arr.asInstanceOf [Array [AnyRef ]], ord.asInstanceOf [Ordering [AnyRef ]])
155
+ // casting the Array[AnyRef] to Array[A] and creating an ArraySeq from it
156
+ // is safe because:
157
+ // - the ArraySeq is immutable, and items that are not of type A
158
+ // cannot be added to it
159
+ // - we know it only contains items of type A (and if this collection
160
+ // contains items of another type, we'd get a CCE anyway)
161
+ // - the cast doesn't actually do anything in the runtime because the
162
+ // type of A is not known and Array[_] is Array[AnyRef]
163
+ immutable.ArraySeq .unsafeWrapArray(arr.asInstanceOf [Array [A ]])
164
+ }
165
+ }
166
+ evaluated = true
167
+ underlying = null
168
+ res
169
+ }
170
+
171
+ private [this ] def elems : SomeSeqOps [A ] = {
172
+ val orig = underlying
173
+ if (evaluated) _sorted else orig
174
+ }
175
+
176
+ def apply (i : Int ): A = _sorted.apply(i)
177
+ def length : Int = elems.length
178
+ def iterator : Iterator [A ] = Iterator .empty ++ _sorted.iterator // very lazy
179
+ override def knownSize : Int = elems.knownSize
180
+ override def isEmpty : Boolean = elems.isEmpty
181
+ override def to [C1 ](factory : Factory [A , C1 ]): C1 = _sorted.to(factory)
182
+ override def reverse : SeqView [A ] = new ReverseSorted
183
+ // we know `_sorted` is either tiny or has efficient random access,
184
+ // so this is acceptable for `reversed`
185
+ override protected def reversed : Iterable [A ] = new ReverseSorted
186
+
187
+ override def sorted [B1 >: A ](implicit ord1 : Ordering [B1 ]): SeqView [A ] =
188
+ if (ord1 == this .ord) this
189
+ else if (ord1.isReverseOf(this .ord)) reverse
190
+ else new Sorted (elems, ord1)
191
+ }
118
192
}
119
193
120
194
/** Explicit instantiation of the `SeqView` trait to reduce class file size in subclasses. */
0 commit comments