Skip to content

Commit b288ecd

Browse files
authored
Merge pull request scala#7708 from joshlemer/set-filterInPlace
Optimize s.c.m.Set#filterInPlace
2 parents d5d397f + c11caa7 commit b288ecd

File tree

2 files changed

+66
-2
lines changed

2 files changed

+66
-2
lines changed

src/library/scala/collection/mutable/Set.scala

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,18 @@ trait SetOps[A, +CC[X], +C <: SetOps[A, CC, C]]
8383
* are removed.
8484
*/
8585
def filterInPlace(p: A => Boolean): this.type = {
86-
for (elem <- this.toList) // scala/bug#7269 toList avoids ConcurrentModificationException
87-
if (!p(elem)) this -= elem
86+
if (nonEmpty) {
87+
val array = this.toArray[Any] // scala/bug#7269 toArray avoids ConcurrentModificationException
88+
val arrayLength = array.length
89+
var i = 0
90+
while (i < arrayLength) {
91+
val elem = array(i).asInstanceOf[A]
92+
if (!p(elem)) {
93+
this -= elem
94+
}
95+
i += 1
96+
}
97+
}
8898
this
8999
}
90100

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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.collection.mutable
14+
15+
import org.scalacheck._
16+
import org.scalacheck.Prop._
17+
import org.scalacheck.Arbitrary.arbitrary
18+
import Gen._
19+
20+
21+
object SetProperties extends Properties("mutable.Set") {
22+
23+
type Elem = Int
24+
25+
/** returns a set that certainly does not override `filterInPlace` implementation */
26+
def testSet(elems: collection.immutable.Set[Elem]): Set[Elem] = new Set[Elem] {
27+
override protected[this] def className: String = "TestSet"
28+
private[this] var _elems = elems
29+
override def iterator: Iterator[Elem] = _elems.iterator
30+
override def clear(): Unit = _elems = collection.immutable.Set.empty
31+
override def subtractOne(elem: Elem): this.type = { _elems -= elem; this }
32+
override def addOne(elem: Elem): this.type = { _elems += elem; this }
33+
override def contains(elem: Elem): Boolean = { _elems.contains(elem) }
34+
}
35+
36+
implicit val arbSet: Arbitrary[Set[Elem]] =
37+
Arbitrary {
38+
for {
39+
elems <- arbitrary[collection.immutable.HashSet[Elem]]
40+
set <- oneOf(
41+
elems.to(HashSet),
42+
elems.to(TreeSet),
43+
elems.to(LinkedHashSet),
44+
testSet(elems)
45+
)
46+
} yield set
47+
}
48+
49+
property("filterInPlace(p)") = forAll { (set: Set[Elem], p: Elem => Boolean) =>
50+
val expected: collection.Set[Elem] = set.to(collection.immutable.HashSet).filter(p)
51+
set.filterInPlace(p)
52+
(set: collection.Set[Elem]) ?= expected
53+
}
54+
}

0 commit comments

Comments
 (0)