2015-11-15 34 views
3

我有一個正常的名單,並在其上定義了兩個過濾器。我使用第一個過濾器過濾列表,然後使用下一個過濾器過濾輸出並獲取最後一個元素。斯卡拉懶惰收集可以請一些人解釋以下行爲

  1. 我做的List對象LST上述操作(常規列表)
  2. 我做的lst.view上述操作(LAZY LIST)

第二次行動似乎採取更多的迭代。它似乎重新在一點重新開始操作。請找到下面的代碼。有人可以解釋一下原因嗎?

object SolutionTest { 
    val lst = List(("Mark", 32), ("Bob", 22), ("Jane", 8), ("Jill", 21),("Nick", 50), ("Nancy", 42), ("Mike", 19), ("Sara", 12), ("Paula", 42),("John", 21)) 
               //> lst : List[(String, Int)] = List((Mark,32), (Bob,22), (Jane,8), (Jill,21), 
               //| (Nick,50), (Nancy,42), (Mike,19), (Sara,12), (Paula,42), (John,21)) 
    lst.size         //> res0: Int = 10 

    def filter1(tup:(String, Int)):Boolean={ 
    println("from filter1 "+ tup) 
    val (_, age) = tup 
    age > 17 
    }            //> filter1: (tup: (String, Int))Boolean 

    def filter2(tup:(String, Int)):Boolean={ 
    println("from filter2 "+ tup) 
    val (name, _) = tup 
    name.startsWith("J") 
    }            //> filter2: (tup: (String, Int))Boolean 


//NORMAL LIST             
lst.filter(filter1).filter(filter2).last //> from filter1 (Mark,32) 
               //| from filter1 (Bob,22) 
               //| from filter1 (Jane,8) 
               //| from filter1 (Jill,21) 
               //| from filter1 (Nick,50) 
               //| from filter1 (Nancy,42) 
               //| from filter1 (Mike,19) 
               //| from filter1 (Sara,12) 
               //| from filter1 (Paula,42) 
               //| from filter1 (John,21) 
               //| from filter2 (Mark,32) 
               //| from filter2 (Bob,22) 
               //| from filter2 (Jill,21) 
               //| from filter2 (Nick,50) 
               //| from filter2 (Nancy,42) 
               //| from filter2 (Mike,19) 
               //| from filter2 (Paula,42) 
               //| from filter2 (John,21) 
               //| res1: (String, Int) = (John,21) 

//LAZY LIST 
lst.view.filter(filter1).filter(filter2).last 
               //> from filter1 (Mark,32) 
               //| from filter2 (Mark,32) 
               //| from filter1 (Bob,22) 
               //| from filter2 (Bob,22) 
               //| from filter1 (Jane,8) 
               //| from filter1 (Jill,21) 
               //| from filter2 (Jill,21) 
               //| from filter1 (Mark,32) RESTARTING THE OPERATION HERE!!! 
               //| from filter2 (Mark,32) 
               //| from filter1 (Bob,22) 
               //| from filter2 (Bob,22) 
               //| from filter1 (Jane,8) 
               //| from filter1 (Jill,21) 
               //| from filter2 (Jill,21) 
               //| from filter1 (Nick,50) 
               //| from filter2 (Nick,50) 
               //| from filter1 (Nancy,42) 
               //| from filter2 (Nancy,42) 
               //| from filter1 (Mike,19) 
               //| from filter2 (Mike,19) 
               //| from filter1 (Sara,12) 
               //| from filter1 (Paula,42) 
               //| from filter2 (Paula,42) 
               //| from filter1 (John,21) 
               //| from filter2 (John,21) 
               //| res2: (String, Int) = (John,21) 
} 
+0

@kolmar回答得很好。爲避免在視圖中使用「last」時的額外處理,請在過濾器之後放置「force」:'lst.view.filter(filter1).filter(filter2).force.last' –

回答

6

在您的評論「RESTARTING HERE」之前的第一個操作來自於查找已過濾的序列中的第一個元素。 Scala開始過濾,直到找到結果(Jill,21)中的第一個元素。之後它實際上開始處理整個序列。

這是因爲lastTraversableLikeimplemented這樣的:

def last: A = { 
    var lst = head 
    for (x <- this) 
    lst = x 
    lst 
} 

它通過序列真的會前調用head。簡單的view s不要使用緩存,所以經過篩選找到head後,它必須重新啓動。

視圖上的其他功能可能無法顯示此重新啓動行爲。例如lst.view.filter(filter1).filter(filter2).lastOption只能運行一次序列。

相關問題