Проблема, как говорили другие, заключается в том, что filter
создает новую коллекцию.Альтернатива withFilter
не имеет, но у нее нет foldLeft
.Кроме того, использование .view
, .iterator
или .toStream
позволит избежать создания новой коллекции различными способами, но здесь все они работают медленнее, чем первый использованный вами метод, который сначала мне показался несколько странным.
Но тогда ... Понимаете, 1 until 1000
- это Range
, размер которого на самом деле очень мал, потому что он не хранит каждый элемент.Кроме того, Range
foreach
чрезвычайно оптимизирован и даже specialized
, что не относится ни к одной из других коллекций.Поскольку foldLeft
реализован как foreach
, пока вы остаетесь с Range
, вы можете наслаждаться его оптимизированными методами.
(_: Range).foreach
:
@inline final override def foreach[@specialized(Unit) U](f: Int => U) {
if (length > 0) {
val last = this.last
var i = start
while (i != last) {
f(i)
i += step
}
f(i)
}
}
(_: Range).view.foreach
def foreach[U](f: A => U): Unit =
iterator.foreach(f)
(_: Range).view.iterator
override def iterator: Iterator[A] = new Elements(0, length)
protected class Elements(start: Int, end: Int) extends BufferedIterator[A] with Serializable {
private var i = start
def hasNext: Boolean = i < end
def next: A =
if (i < end) {
val x = self(i)
i += 1
x
} else Iterator.empty.next
def head =
if (i < end) self(i) else Iterator.empty.next
/** $super
* '''Note:''' `drop` is overridden to enable fast searching in the middle of indexed sequences.
*/
override def drop(n: Int): Iterator[A] =
if (n > 0) new Elements(i + n, end) else this
/** $super
* '''Note:''' `take` is overridden to be symmetric to `drop`.
*/
override def take(n: Int): Iterator[A] =
if (n <= 0) Iterator.empty.buffered
else if (i + n < end) new Elements(i, i + n)
else this
}
(_: Range).view.iterator.foreach
def foreach[U](f: A => U) { while (hasNext) f(next()) }
И это, конечно, даже не считается filter
между view
и foldLeft
:
override def filter(p: A => Boolean): This = newFiltered(p).asInstanceOf[This]
protected def newFiltered(p: A => Boolean): Transformed[A] = new Filtered { val pred = p }
trait Filtered extends Transformed[A] {
protected[this] val pred: A => Boolean
override def foreach[U](f: A => U) {
for (x <- self)
if (pred(x)) f(x)
}
override def stringPrefix = self.stringPrefix+"F"
}