在試圖理解流,迭代器和集合視圖之間的差異時,我偶然發現了以下奇怪的行爲。scala視圖篩選器不是懶惰?
下面的代碼(映射和過濾器只需打印他們的意見,並將它轉發不變):
object ArrayViewTest {
def main(args: Array[String]) {
val array = Array.range(1,10)
print("stream-map-head: ")
array.toStream.map(x => {print(x); x}).head
print("\nstream-filter-head: ")
array.toStream.filter(x => {print(x); true}).head
print("\niterator-map-head: ")
array.iterator.map(x => {print(x); x}).take(1).toArray
print("\niterator-filter-head: ")
array.iterator.filter(x => {print(x); true}).take(1).toArray
print("\nview-map-head: ")
array.view.map(x => {print(x); x}).head
print("\nview-filter-head: ")
array.view.filter(x => {print(x); true}).head
}
}
,其輸出:
stream-map-head: 1
stream-filter-head: 1
iterator-map-head: 1
iterator-filter-head: 1
view-map-head: 1
view-filter-head: 123456789 // <------ WHY ?
爲什麼過濾呼籲,全陣列的圖過程? 我希望過濾器的評估只能通過調用head來驅動一次,就像在所有其他情況下一樣,特別是在使用地圖時。
我缺少哪些洞察力?
(上發表評論迷你側的問題,爲什麼沒有腦袋上的迭代器?)
編輯: 同樣奇怪的行爲(如這裏scala.Array.range(1,10)
)由scala.collection.mutable.ArraySeq.range(1,10)
,scala.collection.mutable.ArrayBuffer.range(1,10)
實現,和scala.collection.mutable.StringBuilder.newBuilder.append("123456789")
。 但是,對於所有其他可變集合以及所有不可變集合,視圖上的過濾器按預期工作,並輸出1
。
(微型側回答)時,如果你想獲得迭代器的第一個元素使用
filter
而不是當情況發生時,Filtered
特點是隻用你將不得不提前使用'next'並調用它兩次會有問題。 –