Supponiamo di avere una raccolta di valori iterabile molto grande (nell'ordine di 100.000 voci di stringa, leggere dal disco uno per uno) e faccio qualcosa sul suo prodotto cartesiano (e scrivo il risultato indietro su disco, anche se non voglio dimostrare che qui):Scala per loop ed iteratori
for(v1 <- values; v2 <- values) yield ((v1, v2), 1)
capisco che questo è solo un altro modo di scrivere
values.flatMap(v1 => values.map(v2 => ((v1, v2), 1)))
questo fa sì che a quanto pare l'intera collezione per ogni iterazione flatMap (o anche l'intero prodotto cartesiano?) da conservare in memoria. Se leggi la prima versione usando il ciclo for questo ovviamente non è necessario. Idealmente, solo due voci (quelle combinate) dovrebbero essere conservate in memoria in ogni momento.
Se riformulare il prima versione come questa:
for(v1 <- values.iterator; v2 <- values.iterator) yield ((v1, v2), 1)
consumo di memoria è molto più basso, portandomi a pensare che questa versione deve essere fondamentalmente diverso. Cosa fa esattamente nella seconda versione? Perché Scala non utilizza implicitamente gli iteratori per la prima versione? C'è qualche accelerazione quando non si usano gli iteratori in alcune circostanze?
Grazie! (E anche grazie a "lmm" che ha risposto a una precedente versione di questa domanda)
Se si restituisce un '((v1, v2), 1)' si crea una nuova raccolta contenente tutte quelle tuple. Quindi, in effetti, l'intero prodotto cartesiano dovrà essere conservato in memoria, no? –
Non necessariamente, vengono scritti di nuovo sul disco (usando spark/HDFS). Altrimenti non scalerebbe troppo bene :) – Johannes