Skip to content

Commit 6cf527f

Browse files
authored
Merge pull request scala/scala#8497 from retronym/faster/set-iterator
Optimized immutable.SetN.{filter, iterator}
2 parents 1df6e70 + c8bd61a commit 6cf527f

File tree

2 files changed

+140
-3
lines changed

2 files changed

+140
-3
lines changed

library/src/scala/collection/immutable/Map.scala

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,10 @@ object Map extends MapFactory[Map] {
253253
override def foreach[U](f: ((K, V)) => U): Unit = {
254254
f((key1, value1))
255255
}
256+
override def exists(p: ((K, V)) => Boolean): Boolean = p((key1, value1))
257+
override def forall(p: ((K, V)) => Boolean): Boolean = p((key1, value1))
258+
override protected[collection] def filterImpl(pred: ((K, V)) => Boolean, isFlipped: Boolean): Map[K, V] =
259+
if (pred((key1, value1)) != isFlipped) this else Map.empty
256260
override def transform[W](f: (K, V) => W): Map[K, W] = {
257261
val walue1 = f(key1, value1)
258262
if (walue1.asInstanceOf[AnyRef] eq value1.asInstanceOf[AnyRef]) this.asInstanceOf[Map[K, W]]
@@ -330,6 +334,21 @@ object Map extends MapFactory[Map] {
330334
override def foreach[U](f: ((K, V)) => U): Unit = {
331335
f((key1, value1)); f((key2, value2))
332336
}
337+
override def exists(p: ((K, V)) => Boolean): Boolean = p((key1, value1)) || p((key2, value2))
338+
override def forall(p: ((K, V)) => Boolean): Boolean = p((key1, value1)) && p((key2, value2))
339+
override protected[collection] def filterImpl(pred: ((K, V)) => Boolean, isFlipped: Boolean): Map[K, V] = {
340+
var k1 = null.asInstanceOf[K]
341+
var v1 = null.asInstanceOf[V]
342+
var n = 0
343+
if (pred((key1, value1)) != isFlipped) { {k1 = key1; v1 = value1}; n += 1}
344+
if (pred((key2, value2)) != isFlipped) { if (n == 0) {k1 = key2; v1 = value2}; n += 1}
345+
346+
n match {
347+
case 0 => Map.empty
348+
case 1 => new Map1(k1, v1)
349+
case 2 => this
350+
}
351+
}
333352
override def transform[W](f: (K, V) => W): Map[K, W] = {
334353
val walue1 = f(key1, value1)
335354
val walue2 = f(key2, value2)
@@ -420,6 +439,23 @@ object Map extends MapFactory[Map] {
420439
override def foreach[U](f: ((K, V)) => U): Unit = {
421440
f((key1, value1)); f((key2, value2)); f((key3, value3))
422441
}
442+
override def exists(p: ((K, V)) => Boolean): Boolean = p((key1, value1)) || p((key2, value2)) || p((key3, value3))
443+
override def forall(p: ((K, V)) => Boolean): Boolean = p((key1, value1)) && p((key2, value2)) && p((key3, value3))
444+
override protected[collection] def filterImpl(pred: ((K, V)) => Boolean, isFlipped: Boolean): Map[K, V] = {
445+
var k1, k2 = null.asInstanceOf[K]
446+
var v1, v2 = null.asInstanceOf[V]
447+
var n = 0
448+
if (pred((key1, value1)) != isFlipped) { { k1 = key1; v1 = value1 }; n += 1}
449+
if (pred((key2, value2)) != isFlipped) { if (n == 0) { k1 = key2; v1 = value2 } else { k2 = key2; v2 = value2 }; n += 1}
450+
if (pred((key3, value3)) != isFlipped) { if (n == 0) { k1 = key3; v1 = value3 } else if (n == 1) { k2 = key3; v2 = value3 }; n += 1}
451+
452+
n match {
453+
case 0 => Map.empty
454+
case 1 => new Map1(k1, v1)
455+
case 2 => new Map2(k1, v1, k2, v2)
456+
case 3 => this
457+
}
458+
}
423459
override def transform[W](f: (K, V) => W): Map[K, W] = {
424460
val walue1 = f(key1, value1)
425461
val walue2 = f(key2, value2)
@@ -525,6 +561,25 @@ object Map extends MapFactory[Map] {
525561
override def foreach[U](f: ((K, V)) => U): Unit = {
526562
f((key1, value1)); f((key2, value2)); f((key3, value3)); f((key4, value4))
527563
}
564+
override def exists(p: ((K, V)) => Boolean): Boolean = p((key1, value1)) || p((key2, value2)) || p((key3, value3)) || p((key4, value4))
565+
override def forall(p: ((K, V)) => Boolean): Boolean = p((key1, value1)) && p((key2, value2)) && p((key3, value3)) && p((key4, value4))
566+
override protected[collection] def filterImpl(pred: ((K, V)) => Boolean, isFlipped: Boolean): Map[K, V] = {
567+
var k1, k2, k3 = null.asInstanceOf[K]
568+
var v1, v2, v3 = null.asInstanceOf[V]
569+
var n = 0
570+
if (pred((key1, value1)) != isFlipped) { { k1 = key1; v1 = value1 }; n += 1}
571+
if (pred((key2, value2)) != isFlipped) { if (n == 0) { k1 = key2; v1 = value2 } else { k2 = key2; v2 = value2 }; n += 1}
572+
if (pred((key3, value3)) != isFlipped) { if (n == 0) { k1 = key3; v1 = value3 } else if (n == 1) { k2 = key3; v2 = value3 } else { k3 = key3; v3 = value3}; n += 1}
573+
if (pred((key4, value4)) != isFlipped) { if (n == 0) { k1 = key4; v1 = value4 } else if (n == 1) { k2 = key4; v2 = value4 } else if (n == 2) { k3 = key4; v3 = value4 }; n += 1}
574+
575+
n match {
576+
case 0 => Map.empty
577+
case 1 => new Map1(k1, v1)
578+
case 2 => new Map2(k1, v1, k2, v2)
579+
case 3 => new Map3(k1, v1, k2, v2, k3, v3)
580+
case 4 => this
581+
}
582+
}
528583
override def transform[W](f: (K, V) => W): Map[K, W] = {
529584
val walue1 = f(key1, value1)
530585
val walue2 = f(key2, value2)

library/src/scala/collection/immutable/Set.scala

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,30 @@ object Set extends IterableFactory[Set] {
127127
}
128128
private[collection] def emptyInstance: Set[Any] = EmptySet
129129

130+
@SerialVersionUID(3L)
131+
private abstract class SetNIterator[A](n: Int) extends AbstractIterator[A] with Serializable {
132+
private[this] var current = 0
133+
private[this] var remainder = n
134+
override def knownSize: Int = remainder
135+
def hasNext = remainder > 0
136+
def apply(i: Int): A
137+
def next(): A =
138+
if (hasNext) {
139+
val r = apply(current)
140+
current += 1
141+
remainder -= 1
142+
r
143+
} else Iterator.empty.next()
144+
145+
override def drop(n: Int): Iterator[A] = {
146+
if (n > 0) {
147+
current += n
148+
remainder = Math.max(0, remainder - n)
149+
}
150+
this
151+
}
152+
}
153+
130154
/** An optimized representation for immutable sets of size 1 */
131155
@SerialVersionUID(3L)
132156
final class Set1[A] private[collection] (elem1: A) extends AbstractSet[A] with StrictOptimizedIterableOps[A, Set, Set[A]] with Serializable {
@@ -144,6 +168,9 @@ object Set extends IterableFactory[Set] {
144168
override def foreach[U](f: A => U): Unit = f(elem1)
145169
override def exists(p: A => Boolean): Boolean = p(elem1)
146170
override def forall(p: A => Boolean): Boolean = p(elem1)
171+
override protected[collection] def filterImpl(pred: A => Boolean, isFlipped: Boolean): Set[A] =
172+
if (pred(elem1) != isFlipped) this else Set.empty
173+
147174
override def find(p: A => Boolean): Option[A] =
148175
if (p(elem1)) Some(elem1)
149176
else None
@@ -165,7 +192,11 @@ object Set extends IterableFactory[Set] {
165192
if (elem == elem1) new Set1(elem2)
166193
else if (elem == elem2) new Set1(elem1)
167194
else this
168-
def iterator: Iterator[A] = (elem1 :: elem2 :: Nil).iterator
195+
def iterator: Iterator[A] = new SetNIterator[A](size) {
196+
def apply(i: Int) = getElem(i)
197+
}
198+
private def getElem(i: Int) = i match { case 0 => elem1 case 1 => elem2 }
199+
169200
override def foreach[U](f: A => U): Unit = {
170201
f(elem1); f(elem2)
171202
}
@@ -175,6 +206,18 @@ object Set extends IterableFactory[Set] {
175206
override def forall(p: A => Boolean): Boolean = {
176207
p(elem1) && p(elem2)
177208
}
209+
override protected[collection] def filterImpl(pred: A => Boolean, isFlipped: Boolean): Set[A] = {
210+
var r1: A = null.asInstanceOf[A]
211+
var n = 0
212+
if (pred(elem1) != isFlipped) { r1 = elem1; n += 1}
213+
if (pred(elem2) != isFlipped) { if (n == 0) r1 = elem2; n += 1}
214+
215+
n match {
216+
case 0 => Set.empty
217+
case 1 => new Set1(r1)
218+
case 2 => this
219+
}
220+
}
178221
override def find(p: A => Boolean): Option[A] = {
179222
if (p(elem1)) Some(elem1)
180223
else if (p(elem2)) Some(elem2)
@@ -200,7 +243,11 @@ object Set extends IterableFactory[Set] {
200243
else if (elem == elem2) new Set2(elem1, elem3)
201244
else if (elem == elem3) new Set2(elem1, elem2)
202245
else this
203-
def iterator: Iterator[A] = (elem1 :: elem2 :: elem3 :: Nil).iterator
246+
def iterator: Iterator[A] = new SetNIterator[A](size) {
247+
def apply(i: Int) = getElem(i)
248+
}
249+
private def getElem(i: Int) = i match { case 0 => elem1 case 1 => elem2 case 2 => elem3 }
250+
204251
override def foreach[U](f: A => U): Unit = {
205252
f(elem1); f(elem2); f(elem3)
206253
}
@@ -210,6 +257,20 @@ object Set extends IterableFactory[Set] {
210257
override def forall(p: A => Boolean): Boolean = {
211258
p(elem1) && p(elem2) && p(elem3)
212259
}
260+
override protected[collection] def filterImpl(pred: A => Boolean, isFlipped: Boolean): Set[A] = {
261+
var r1, r2: A = null.asInstanceOf[A]
262+
var n = 0
263+
if (pred(elem1) != isFlipped) { r1 = elem1; n += 1}
264+
if (pred(elem2) != isFlipped) { if (n == 0) r1 = elem2 else r2 = elem2; n += 1}
265+
if (pred(elem3) != isFlipped) { if (n == 0) r1 = elem3 else if (n == 1) r2 = elem3; n += 1}
266+
267+
n match {
268+
case 0 => Set.empty
269+
case 1 => new Set1(r1)
270+
case 2 => new Set2(r1, r2)
271+
case 3 => this
272+
}
273+
}
213274
override def find(p: A => Boolean): Option[A] = {
214275
if (p(elem1)) Some(elem1)
215276
else if (p(elem2)) Some(elem2)
@@ -237,7 +298,11 @@ object Set extends IterableFactory[Set] {
237298
else if (elem == elem3) new Set3(elem1, elem2, elem4)
238299
else if (elem == elem4) new Set3(elem1, elem2, elem3)
239300
else this
240-
def iterator: Iterator[A] = (elem1 :: elem2 :: elem3 :: elem4 :: Nil).iterator
301+
def iterator: Iterator[A] = new SetNIterator[A](size) {
302+
def apply(i: Int) = getElem(i)
303+
}
304+
private def getElem(i: Int) = i match { case 0 => elem1 case 1 => elem2 case 2 => elem3 case 3 => elem4 }
305+
241306
override def foreach[U](f: A => U): Unit = {
242307
f(elem1); f(elem2); f(elem3); f(elem4)
243308
}
@@ -247,6 +312,23 @@ object Set extends IterableFactory[Set] {
247312
override def forall(p: A => Boolean): Boolean = {
248313
p(elem1) && p(elem2) && p(elem3) && p(elem4)
249314
}
315+
override protected[collection] def filterImpl(pred: A => Boolean, isFlipped: Boolean): Set[A] = {
316+
var r1, r2, r3: A = null.asInstanceOf[A]
317+
var n = 0
318+
if (pred(elem1) != isFlipped) { r1 = elem1; n += 1}
319+
if (pred(elem2) != isFlipped) { if (n == 0) r1 = elem2 else r2 = elem2; n += 1}
320+
if (pred(elem3) != isFlipped) { if (n == 0) r1 = elem3 else if (n == 1) r2 = elem3 else r3 = elem3; n += 1}
321+
if (pred(elem4) != isFlipped) { if (n == 0) r1 = elem4 else if (n == 1) r2 = elem4 else if (n == 2) r3 = elem4; n += 1}
322+
323+
n match {
324+
case 0 => Set.empty
325+
case 1 => new Set1(r1)
326+
case 2 => new Set2(r1, r2)
327+
case 3 => new Set3(r1, r2, r3)
328+
case 4 => this
329+
}
330+
}
331+
250332
override def find(p: A => Boolean): Option[A] = {
251333
if (p(elem1)) Some(elem1)
252334
else if (p(elem2)) Some(elem2)

0 commit comments

Comments
 (0)