@@ -228,6 +228,88 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable
228
228
/** A view over the elements of this collection. */
229
229
def view : View [A ] = View .fromIteratorProvider(() => iterator)
230
230
231
+ /** Compares the size of this $coll to a test value.
232
+ *
233
+ * @param otherSize the test value that gets compared with the size.
234
+ * @return A value `x` where
235
+ * {{{
236
+ * x < 0 if this.size < otherSize
237
+ * x == 0 if this.size == otherSize
238
+ * x > 0 if this.size > otherSize
239
+ * }}}
240
+ * The method as implemented here does not call `size` directly; its running time
241
+ * is `O(size min _size)` instead of `O(size)`. The method should be overwritten
242
+ * if computing `size` is cheap.
243
+ */
244
+ def sizeCompare (otherSize : Int ): Int = {
245
+ if (otherSize < 0 ) 1
246
+ else {
247
+ val known = knownSize
248
+ if (known >= 0 ) Integer .compare(known, otherSize)
249
+ else {
250
+ var i = 0
251
+ val it = iterator
252
+ while (it.hasNext) {
253
+ if (i == otherSize) return if (it.hasNext) 1 else 0
254
+ it.next()
255
+ i += 1
256
+ }
257
+ i - otherSize
258
+ }
259
+ }
260
+ }
261
+
262
+ /** Returns a value class containing operations for comparing the size of this $coll to a test value.
263
+ *
264
+ * These operations are implemented in terms of [[sizeCompare(Int) `sizeCompare(Int)` ]], and
265
+ * allow the following more readable usages:
266
+ *
267
+ * {{{
268
+ * this.sizeIs < size // this.sizeCompare(size) < 0
269
+ * this.sizeIs <= size // this.sizeCompare(size) <= 0
270
+ * this.sizeIs == size // this.sizeCompare(size) == 0
271
+ * this.sizeIs != size // this.sizeCompare(size) != 0
272
+ * this.sizeIs >= size // this.sizeCompare(size) >= 0
273
+ * this.sizeIs > size // this.sizeCompare(size) > 0
274
+ * }}}
275
+ */
276
+ @ inline final def sizeIs : IterableOps .SizeCompareOps = new IterableOps .SizeCompareOps (this )
277
+
278
+ /** Compares the size of this $coll to the size of another `Iterable`.
279
+ *
280
+ * @param that the `Iterable` whose size is compared with this $coll's size.
281
+ * {{{
282
+ * x < 0 if this.size < that.size
283
+ * x == 0 if this.size == that.size
284
+ * x > 0 if this.size > that.size
285
+ * }}}
286
+ * The method as implemented here does not call `size` directly; its running time
287
+ * is `O(this.size min that.size)` instead of `O(this.size + that.size)`.
288
+ * The method should be overwritten if computing `size` is cheap.
289
+ */
290
+ def sizeCompare (that : Iterable [_]): Int = {
291
+ val thatKnownSize = that.knownSize
292
+
293
+ if (thatKnownSize >= 0 ) this sizeCompare thatKnownSize
294
+ else {
295
+ val thisKnownSize = this .knownSize
296
+
297
+ if (thisKnownSize >= 0 ) {
298
+ val res = that sizeCompare thisKnownSize
299
+ // can't just invert the result, because `-Int.MinValue == Int.MinValue`
300
+ if (res == Int .MinValue ) 1 else - res
301
+ } else {
302
+ val thisIt = this .iterator
303
+ val thatIt = that.iterator
304
+ while (thisIt.hasNext && thatIt.hasNext) {
305
+ thisIt.next()
306
+ thatIt.next()
307
+ }
308
+ java.lang.Boolean .compare(thisIt.hasNext, thatIt.hasNext)
309
+ }
310
+ }
311
+ }
312
+
231
313
/** A view over a slice of the elements of this collection. */
232
314
@ deprecated(" Use .view.slice(from, until) instead of .view(from, until)" , " 2.13.0" )
233
315
@ `inline` final def view (from : Int , until : Int ): View [A ] = view.slice(from, until)
@@ -690,6 +772,26 @@ trait IterableOps[+A, +CC[_], +C] extends Any with IterableOnce[A] with Iterable
690
772
691
773
object IterableOps {
692
774
775
+ /** Operations for comparing the size of a collection to a test value.
776
+ *
777
+ * These operations are implemented in terms of
778
+ * [[scala.collection.IterableOps.sizeCompare(Int) `sizeCompare(Int)` ]].
779
+ */
780
+ final class SizeCompareOps private [collection](val it : IterableOps [_, AnyConstr , _]) extends AnyVal {
781
+ /** Tests if the size of the collection is less than some value. */
782
+ @ inline def < (size : Int ): Boolean = it.sizeCompare(size) < 0
783
+ /** Tests if the size of the collection is less than or equal to some value. */
784
+ @ inline def <= (size : Int ): Boolean = it.sizeCompare(size) <= 0
785
+ /** Tests if the size of the collection is equal to some value. */
786
+ @ inline def == (size : Int ): Boolean = it.sizeCompare(size) == 0
787
+ /** Tests if the size of the collection is not equal to some value. */
788
+ @ inline def != (size : Int ): Boolean = it.sizeCompare(size) != 0
789
+ /** Tests if the size of the collection is greater than or equal to some value. */
790
+ @ inline def >= (size : Int ): Boolean = it.sizeCompare(size) >= 0
791
+ /** Tests if the size of the collection is greater than some value. */
792
+ @ inline def > (size : Int ): Boolean = it.sizeCompare(size) > 0
793
+ }
794
+
693
795
/** A trait that contains just the `map`, `flatMap`, `foreach` and `withFilter` methods
694
796
* of trait `Iterable`.
695
797
*
0 commit comments