Sự cố, như những người khác đã nói, là filter
tạo bộ sưu tập mới. Thay thế withFilter
thì không, nhưng không có foldLeft
. Ngoài ra, việc sử dụng .view
, .iterator
hoặc .toStream
tất cả sẽ tránh tạo bộ sưu tập mới theo nhiều cách khác nhau, nhưng tất cả đều chậm hơn ở đây so với phương pháp đầu tiên bạn sử dụng.
Nhưng, sau đó ...Xem, 1 until 1000
là một Range
, có kích thước thực sự là rất nhỏ, bởi vì nó không lưu trữ từng phần tử. Ngoài ra, là cực kỳ được tối ưu hóa và thậm chí là specialized
, không phải là trường hợp của bất kỳ bộ sưu tập nào khác. Kể từ khi foldLeft
được triển khai dưới dạng foreach
, miễn là bạn ở lại với một Range
bạn có thể tận hưởng các phương pháp được tối ưu hóa của nó.
(_: 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()) }
Và đó, tất nhiên, thậm chí không đếm filter
giữa view
và 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"
}
Bạn đo lường mã đó như thế nào là "các đơn đặt hàng có cường độ nhanh hơn"? Trên máy tính xách tay * cực kỳ * cũ, * cực kỳ * của tôi, trong trình thông dịch Scala *, phiên bản bạn yêu cầu là "các đơn đặt hàng có cường độ chậm hơn" mất ít hơn 300 µs (đó là * micro * giây), do đó, bao lâu * phiên bản nhanh * có? Liệu nó đi ngược thời gian? Hầu hết các JVM hiệu suất cao cần khoảng 5 * giây * để làm ấm bộ nhớ cache và các công cụ của chúng, trước khi chúng đạt tốc độ tối đa. (Trình biên dịch C2 trong JVM HotSpot, là trình biên dịch tối ưu hóa, thậm chí không biên dịch một phương thức cho đến khi nó chạy 20000 lần.) –
Phiên bản thứ hai có vẻ nhanh hơn gấp 3 lần (bằng cách đo lường hoàn toàn không khoa học của tôi bằng cách sử dụng '(1 đến 10000000) 'trong REPL). Tôi sẽ không gọi đó là "đơn đặt hàng của cường độ", nhưng vẫn còn. –
@ Jörg: bạn có thể thấy thời gian chạy tại liên kết ideone của mình, nhưng tôi sẽ chỉnh sửa thông tin đó vào câu hỏi để nó không bị mất nếu liên kết ideone biến mất. –