Ответ 1
Проблема, как говорили другие, заключается в том, что 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"
}